Leetcode.321 拼接最大数
hard
给定长度分别为 m m m 和 n n n 的两个数组,其元素由 0 ∼ 9 0 \sim 9 0∼9 构成,表示两个自然数各位上的数字。现在从这两个数组中选出 k k k ( k ≤ m + n ) (k \leq m + n) (k≤m+n) 个数字拼接成一个新的数,要求从同一个数组中取出的数字保持其在原数组中的相对顺序。
求满足该条件的最大数。结果返回一个表示该最大数的长度为 k k k 的数组。
说明: 请尽可能地优化你算法的时间和空间复杂度。
输入:
nums1 = [3, 4, 6, 5]
nums2 = [9, 1, 2, 5, 8, 3]
k = 5
输出:
[9, 8, 6, 5, 3]
输入:
nums1 = [6, 7]
nums2 = [6, 0, 4]
k = 5
输出:
[6, 7, 6, 0, 4]
输入:
nums1 = [3, 9]
nums2 = [8, 9]
k = 3
输出:
[9, 8, 9]
我们假设由 k k k 个元素组成的最大数,其中有 x x x 个元素来自 n u m s 1 nums1 nums1,那么就有 k − x k - x k−x 个元素来自 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 个元素构成的最大数(元素之间要保持在集合 S S S 中的相对位置)。
我们最后再将 s 1 s1 s1 和 s 2 s2 s2 拼接成一个最大数 S S S,那么这个 S S S 就是答案之一。所以我们就要遍历 x x x ,求出所有的 S S S,最后返回最大的那个。
在实现上:
m a x _ s e q u e n c e ( S , m ) max\_sequence(S,m) max_sequence(S,m) 可以利用单调栈实现:
在这里需要介绍一个 STL algorithm 库的函数 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);
}
上述这个函数的作用是:判断区间一 [ f i r s t 1 , l a s t 1 ) [first1,last1) [first1,last1) 字典序是否不大于 区间二 [ f i r s t 2 , l a s t 2 ) [first2,last2) [first2,last2)。
true
;false
;时间复杂度: 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;
}
};