
给定长度分别为 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]来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/create-maximum-number 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
采用动态规划,long long 存不下,溢出,采用string,超时
class Solution {
public:
vector<int> maxNumber(vector<int>& nums1, vector<int>& nums2, int k) {
int m = nums1.size(), n = nums2.size();
typedef long long ll;
vector<vector<vector<ll>>> dp(k+1, vector<vector<ll>>(m+1, vector<ll>(n+1, -1)));
dp[0][0][0] = 0;
string str;
for(int t = 1; t <= k; t++)
{
for(int i = 0; i <= m; i++)
{
for(int j = 0; j <= n; j++)
{
if(dp[t-1][i][j] == -1)
continue;
if(i < m)
{
dp[t][i+1][j] = max(dp[t][i+1][j], dp[t-1][i][j]*10+nums1[i]);
dp[t-1][i+1][j] = max(dp[t-1][i+1][j], dp[t-1][i][j]);
}
if(j < n)
{
dp[t][i][j+1] = max(dp[t][i][j+1], dp[t-1][i][j]*10+nums2[j]);
dp[t-1][i][j+1] = max(dp[t-1][i][j+1], dp[t-1][i][j]);
}
}
}
}
vector<int> ans(k, 0);
ll res = 0;
for(int i = 0; i <= m; ++i)
{
for(int j = 0; j <= n; ++j)
res = max(res, dp[k][i][j]);
}
for(int i = k-1; i >= 0; --i)
{
ans[i] = res%10;
res /= 10;
}
return ans;
}
};string 超时
class Solution {
public:
vector<int> maxNumber(vector<int>& nums1, vector<int>& nums2, int k) {
int m = nums1.size(), n = nums2.size();
vector<vector<vector<string>>> dp(k+1, vector<vector<string>>(m+1, vector<string>(n+1, "#")));
dp[0][0][0] = "/";
string str;
for(int t = 1; t <= k; t++)
{
for(int i = 0; i <= m; i++)
{
for(int j = 0; j <= n; j++)
{
if(dp[t-1][i][j] == "#")
continue;
if(i < m)
{
str = to_string(nums1[i]);
dp[t][i+1][j] = max(dp[t][i+1][j], dp[t-1][i][j]+str);
dp[t-1][i+1][j] = max(dp[t-1][i+1][j], dp[t-1][i][j]);
}
if(j < n)
{
str = to_string(nums2[j]);
dp[t][i][j+1] = max(dp[t][i][j+1], dp[t-1][i][j]+str);
dp[t-1][i][j+1] = max(dp[t-1][i][j+1], dp[t-1][i][j]);
}
}
}
}
vector<int> ans(k, 0);
string res = "";
for(int i = 0; i <= m; ++i)
{
for(int j = 0; j <= n; ++j)
res = max(res, dp[k][i][j]);
}
for(int i = 0; i < k; ++i)
ans[i] = res[i+1]-'0';
return ans;
}
};{i, k-i}class Solution {
vector<int> tmp;
public:
vector<int> maxNumber(vector<int>& nums1, vector<int>& nums2, int k) {
int n1 = nums1.size(), n2 = nums2.size();
tmp.resize(k);
int r = min(n1, k);
vector<int> ans;
for(int i = 0; i <= r; ++i)
{
if(k-i > n2)
continue;
auto arr1 = select(nums1, i);
auto arr2 = select(nums2, k-i);
merge(arr1, arr2, ans);
}
return ans;
}
vector<int> select(vector<int>& nums, int k)
{
if(k == nums.size())
return nums;
vector<int> stk;
for(int i = 0; i < nums.size(); ++i)
{
while(!stk.empty() && stk.size()+nums.size()-i > k && stk.back() < nums[i])
stk.pop_back();
stk.push_back(nums[i]);
}
stk.resize(k);
return stk;
}
void merge(vector<int>& a1, vector<int>& a2, vector<int>& ans)
{
int n1 = a1.size(), n2 = a2.size(), i = 0, j = 0, idx = 0;
while(i < n1 && j < n2)
{
if(compare(a1, i, a2, j) >= 0)
tmp[idx++] = a1[i++];
else
tmp[idx++] = a2[j++];
}
while(i < n1)
tmp[idx++] = a1[i++];
while(j < n2)
tmp[idx++] = a2[j++];
if(ans.empty())
ans = tmp;
else if(ans < tmp)
ans = tmp;
}
int compare(vector<int>& a1, int i, vector<int>& a2, int j)
{
int n1 = a1.size(), n2 = a2.size();
while(i < n1 && j < n2)
{
int diff = a1[i] - a2[j];
if(diff != 0)
return diff;
i++,j++;
}
return (n1-i)-(n2-j);//相等话,有剩余的先取
}
};144 ms 20.6 MB C++