思路 :单调栈+自定义归并
1.如果单纯地求一个数组nums[n]固定长度k的最大子数组subnums[k]的话,我们使用贪心+单调栈的思想即可解决。
- 为了保证子数组最大,我们尽可能让大数靠前
- 首先在保证单调栈的长度最终能够大于等于k,在此基础上保证单调栈的元素尽可能地递减
- 扫描一遍数组,记当前遍历的元素位置为p,在保证最后单调栈的长度能够达到k的基础上,依次从栈顶弹出小于nums[p]的元素,然后再加入元素nums[p]。
- 如果栈的元素大于k,需要将多余的元素从栈顶弹出。
2.如果是两个数组nums1[n1]、nums2[n2]组成的子数组nums[k]的话,假设nums1提供了子数组subnums1[i],nums2提供了子数组subnums2[j],k=i+j;则subnums[i]和subnums[j]必然要是从nums1[n1]和nums2[n2]当中挑选的最大子数组,可以根据1进行计算。
3.问题就是如何将subnums[i]和subnums[j]拼接成最大数组。
4.一样采用贪心的思路,尽可能让大数靠前,我们可以参照归并算法,p1遍历subnums1[i],p2遍历subnums2[j]。从subnums1[p1]和subnums2[p2]当中选择较大者将其加入结果数组res当中,那如果两者相等呢? - 考虑这种情况,subnums1[3]={6,7,8},subnums2[4]={6,6,5,4},p1=0,p2=0,如果先加入subnums2[p2]的话,最大的数组也就是6678654,而加入p1的话那就是6786654更大
- 所以我们在两者相等的情况要考虑后面元素的大小,我们选择后面元素更大的对应的那个下标。
- 再考虑这种情况,subnums1[3]={6,7,8},subnums2[4]={6,7,8,9},也就是其中一个数组是另一个的子数组,我们应该先加入更长的那个数组,这样意味着长数组后面那些大元素可以更早暴露,使得大数尽可能靠前。
5.我们只需将k枚举拆解成i和j,然后依次构造相应的最大数组,最后从这些最大数组集中取出最大那个即可。
代码
class Solution {
public:
vector<int> GetSingleStack(vector<int> &nums,int length)
{
if(nums.size()==0||length==0)
return {};
vector<int> res;
res.push_back(nums[0]);
for(int i=1;i<nums.size();i++)
{
while(!res.empty()&&nums[i]>res.back()&&res.size()+nums.size()-i>length)
{
res.pop_back();
}
res.push_back(nums[i]);
}
return vector<int>(res.begin(),res.begin()+length);
}
vector<int> merge_sort(vector<int>& nums1, vector<int>& nums2)
{
vector<int> res;
int p1=0;
int p2=0;
while(p1<nums1.size()&&p2<nums2.size())
{
if(cmp(nums1,p1,nums2,p2))
{
res.push_back(nums1[p1]);
p1++;
}
else
{
res.push_back(nums2[p2]);
p2++;
}
}
while(p1<nums1.size())
{
res.push_back(nums1[p1++]);
}
while(p2<nums2.size())
{
res.push_back(nums2[p2++]);
}
return res;
}
bool cmp(vector<int>& nums1,int p1,vector<int>& nums2,int p2)
{
while(p1<nums1.size()&&p2<nums2.size())
{
if(nums1[p1]==nums2[p2])
{
p1++;
p2++;
}
else if(nums1[p1]>nums2[p2])
{
return true;
}
else
{
return false;
}
}
return p1<nums1.size();
}
vector<int> maxNumber(vector<int>& nums1, vector<int>& nums2, int k) {
vector<int> res;
for(int i=0;i<=k;i++)
{
int j=k-i;
if(i<=nums1.size()&&j<=nums2.size())
{
vector<int> t1=GetSingleStack(nums1,i);
vector<int> t2=GetSingleStack(nums2,j);
vector<int> t3=merge_sort(t1,t2);
if(res.empty())
res=t3;
else
res=cmp(res,0,t3,0)?res:t3;
}
}
return res;
}
};