题目
给定长度分别为 m 和 n 的两个数组,其元素由 0-9 构成,表示两个自然数各位上的数字。现在从这两个数组中选出 k (k <= m + n) 个数字拼接成一个新的数,要求从同一个数组中取出的数字保持其在原数组中的相对顺序。
求满足该条件的最大数。结果返回一个表示该最大数的长度为 k 的数组。
说明: 请尽可能地优化你算法的时间和空间复杂度。
示例 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]
解题思路
- 将这个题目转换成从两个序列中抽取k1 和 k2个数(每个序列中抽取的数保持原有的前后顺序),k1+k2=k。
- 将提取的两组序列采用归并排序的思想进行合并。唯一需要考虑两个数相同的情况。
- 将这k种中取最大的那一个。
单个序列取k个最大的序列可以利用栈的思想,栈顶小于当前的元素就出栈,直到栈顶元素大于当前元素就把当前元素入栈。
代码
class Solution {
public:
vector<int> getMaxSeq(const vector<int>& nums1, int k)
{
vector<int> out;
if (nums1.size() < k)
{
return out;
}
int m = nums1.size() - k;
if (k == 0)
{
return out;
}
for (int i = 0; i < nums1.size(); i++)
{
while (m && out.size()> 0 && out[out.size() - 1] < nums1[i])
{
out.pop_back();
m = m - 1;
}
out.push_back(nums1[i]);
}
return std::vector<int>(out.begin(), out.begin() + k);
}
bool bComBigger(const std::vector<int> &sq1, const std::vector<int> &sq2)
{
int maxLen = std::max(sq1.size(), sq2.size());
int minLen = std::min(sq1.size(), sq2.size());
for (int i = 0; i < minLen; i++)
{
if (sq1[i] > sq2[i])
{
return false;
}
else if (sq1[i] < sq2[i])
{
return true;
}
}
if (sq1.size() < sq2.size())
{
return true;
}
return false;
}
bool bComBiggerOrg(const std::vector<int> &sq1, const std::vector<int> &sq2)
{
if (sq1.size() < sq2.size())
{
return true;
}
else if (sq1.size() > sq2.size())
{
return false;
}
for (int i = 0; i < sq1.size(); i++)
{
if (sq1[i] > sq2[i])
{
return false;
}
else if (sq1[i] < sq2[i])
{
return true;
}
}
return false;
}
vector<int> merge(const vector<int>& nums1, const vector<int>& nums2)
{
vector<int> out(nums1.size() + nums2.size());
int k = 0;
int i = 0;
int j = 0;
while (i < nums1.size() && j < nums2.size())
{
if (nums1[i] > nums2[j])
{
out[k++] = nums1[i++];
}
else if (nums1[i] < nums2[j])
{
out[k++] = nums2[j++];
}
else
{
bool flag = bComBigger(std::vector<int>(nums1.begin() + i, nums1.end()), std::vector<int>(nums2.begin() + j, nums2.end()));
if (flag)
{
out[k++] = nums2[j++];
}
else
{
out[k++] = nums1[i++];
}
}
}
while (i < nums1.size())
{
out[k++] = nums1[i++];
}
while (j < nums2.size())
{
out[k++] = nums2[j++];
}
return out;
}
vector<int> maxNumber(vector<int>& nums1, vector<int>& nums2, int k) {
std::vector<int> out;
for (int i = 0; i <= k; i++)
{
std::vector<int> sq1 = getMaxSeq(nums1, i);
std::vector<int> sq2 = getMaxSeq(nums2, k - i);
std::vector<int> sq = merge(sq1, sq2);
if (bComBiggerOrg(out, sq))
{
out = std::move(sq);
}
}
return out;
}
};