商務(wù)網(wǎng)站建設(shè)需要多少錢seo常用的優(yōu)化工具
題目鏈接
Leetcode.321 拼接最大數(shù)
hard
題目描述
給定長(zhǎng)度分別為 m m m 和 n n n 的兩個(gè)數(shù)組,其元素由 0 ~ 9 0 \sim 9 0~9 構(gòu)成,表示兩個(gè)自然數(shù)各位上的數(shù)字?,F(xiàn)在從這兩個(gè)數(shù)組中選出 k k k ( k ≤ m + n ) (k \leq m + n) (k≤m+n) 個(gè)數(shù)字拼接成一個(gè)新的數(shù),要求從同一個(gè)數(shù)組中取出的數(shù)字保持其在原數(shù)組中的相對(duì)順序。
求滿足該條件的最大數(shù)。結(jié)果返回一個(gè)表示該最大數(shù)的長(zhǎng)度為 k k k 的數(shù)組。
說(shuō)明: 請(qǐng)盡可能地優(yōu)化你算法的時(shí)間和空間復(fù)雜度。
示例 1:
輸入:
nums1 = [3, 4, 6, 5]
nums2 = [9, 1, 2, 5, 8, 3]
k = 5
輸出:
[9, 8, 6, 5, 3]
示例 2:
輸入:
nums1 = [6, 7]
nums2 = [6, 0, 4]
k = 5
輸出:
[6, 7, 6, 0, 4]
示例 3:
輸入:
nums1 = [3, 9]
nums2 = [8, 9]
k = 3
輸出:
[9, 8, 9]
解法:單調(diào)棧
我們假設(shè)由 k k k 個(gè)元素組成的最大數(shù),其中有 x x x 個(gè)元素來(lái)自 n u m s 1 nums1 nums1,那么就有 k ? x k - x k?x 個(gè)元素來(lái)自 n u m s 2 nums2 nums2。
我們定義 m a x _ s e q u e n c e ( S , m ) max\_sequence(S,m) max_sequence(S,m) 表示從集合 S S S 中,選出 m m m 個(gè)元素構(gòu)成的最大數(shù)(元素之間要保持在集合 S S S 中的相對(duì)位置)。
- s 1 = m a x _ s e q u e n c e ( n u m s 1 , x ) s1 = max\_sequence(nums1,x) s1=max_sequence(nums1,x), s 1 s1 s1 表示從集合 n u m s 1 nums1 nums1 中選出 x x x 個(gè)元素組成的最大數(shù);
- s 2 = m a x _ s e q u e n c e ( n u m s 2 , k ? x ) s2 = max\_sequence(nums2,k-x) s2=max_sequence(nums2,k?x), s 2 s2 s2 表示從集合 n u m s 2 nums2 nums2 中選出 k ? x k-x k?x 個(gè)元素組成的最大數(shù);
我們最后再將 s 1 s1 s1 和 s 2 s2 s2 拼接成一個(gè)最大數(shù) S S S,那么這個(gè) S S S 就是答案之一。所以我們就要遍歷 x x x ,求出所有的 S S S,最后返回最大的那個(gè)。
在實(shí)現(xiàn)上:
m a x _ s e q u e n c e ( S , m ) max\_sequence(S,m) max_sequence(S,m) 可以利用單調(diào)棧實(shí)現(xiàn):
- 如果 S . s i z e ( ) ≤ m S.size() \leq m S.size()≤m,那么直接返回集合 S S S 即可;
- 我們定義一個(gè)棧 s t k stk stk,因?yàn)槲覀円祷氐氖? m m m 個(gè)元素組成的最大數(shù),也就是說(shuō) s t k stk stk 最終有 m m m 個(gè)元素,即 s t k stk stk 能夠彈出去的元素最多只有 d e l = S . s i z e ( ) ? m del = S.size() - m del=S.size()?m 個(gè)。
- 假設(shè)當(dāng)前遍歷到的元素為 x x x,如果 x > s t k . t o p ( ) x > stk.top() x>stk.top() 并且 d e l > 0 del > 0 del>0,那么就可以彈出棧頂元素,因?yàn)槲覀円?span id="vxwlu0yf4" class="katex--inline"> s t k stk stk 中的數(shù)字典序盡可能的大。
- 最終返回 s t k stk stk 即可。需要注意的是:如果 S S S 中所有元素都相同 或者 S S S 是一個(gè)非降序的序列,那么 s t k stk stk 中就沒(méi)有彈出的元素,一共就有 S . s i z e ( ) S.size() S.size() 個(gè)元素,我們只需要前 m m m 個(gè)即可。
在這里需要介紹一個(gè) STL algorithm 庫(kù)的函數(shù) lexicographical_compare(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2)
template<class InputIt1, class InputIt2>
bool lexicographical_compare(InputIt1 first1, InputIt1 last1,InputIt2 first2, InputIt2 last2)
{for (; (first1 != last1) && (first2 != last2); ++first1, (void) ++first2){if (*first1 < *first2)return true;if (*first2 < *first1)return false;}return (first1 == last1) && (first2 != last2);
}
上述這個(gè)函數(shù)的作用是:判斷區(qū)間一 [ f i r s t 1 , l a s t 1 ) [first1,last1) [first1,last1) 字典序是否不大于 區(qū)間二 [ f i r s t 2 , l a s t 2 ) [first2,last2) [first2,last2)。
- 是的話,最終返回
true
; - 否,返回
false
;
時(shí)間復(fù)雜度: O ( m + n + k 2 ) O(m + n + k^2) O(m+n+k2)
C++代碼:
class Solution {
public:vector<int> max_sequence(vector<int> vec,int k){int n = vec.size();if(n <= k) return vec;vector<int> stk;int del = n - k;for(int i = 0;i < n;i++){while(stk.size() && vec[i] > stk.back() && del){del--;stk.pop_back();}stk.push_back(vec[i]);}stk.resize(k);return stk;}vector<int> maxNumber(vector<int>& nums1, vector<int>& nums2, int k) {int m = nums1.size() , n = nums2.size();vector<int> res(k,0);for(int x = max(0,k - n);x <= min(k,m);x++){vector<int> temp;auto s1 = max_sequence(nums1,x);auto s2 = max_sequence(nums2,k - x);auto it1 = s1.begin() , it2 = s2.begin();while(it1 != s1.end() || it2 != s2.end()){temp.push_back(lexicographical_compare(it1,s1.end(),it2,s2.end() )? *it2++ : *it1++);}res = lexicographical_compare(res.begin(),res.end(),temp.begin(),temp.end()) ? move(temp) : res;}return res;}
};