topic:
Given two arrays of length m and n with digits 0-9 representing two numbers. Create the maximum number of length k <= m + n from digits of the two. The relative order of the digits from the same array must be preserved. Return an array of the k digits.
Wrong solution: dynamic programming
The question can be expressed as choosing k numbers from m+n numbers to maximize the number of combinations. It is easy to think of the 01 knapsack problem. Choose a number from the number sequence with the "knapsack capacity" of k to maximize the number of combinations.
But in fact, this problem does not have an optimal substructure, which is different from the value accumulation of the 01 knapsack problem. In the 01 knapsack problem, the solution that maximizes the value of the first k items must also maximize the value of the first k-1 items. On the standard of maintaining the original order of numbers to form the largest number, the optimal solution of a small-scale problem cannot be used as the basis for the optimal solution of a large-scale problem, so dynamic programming cannot be used for this problem.
The following are the pits I have stepped on, not ac.
nums1
Length len1
, nums2
length len2
, len=len1+len2
use a structure to represent the number selection plan:
struct selection{
vector<int> n1, n2;
};
- The selection state
selection dp[i][x],0<=i<=len,0<=x<=k
representsnums
the scheme of taking x number from the first i numbers (0~i-1), so that the number of x numberscreate()
generated according to the rule is the largest. - State transition equation
- If you choose nums[i-1], the temporary scheme temp1
- 0<=i-1<len1 The
temporary plan is:
temp1 = dp[i-1][x-1]
temp1.n1.emplace_back(nums[i-1])
- The
temporary plan for len1<=i<len is:
temp1 = dp[i-1][x-1]
temp1.n2.emplace_back(nums[i-1])
- 0<=i-1<len1 The
- If nums[i] is not selected, temporary scheme temp2
temp2 = dp[i-1][x]
- If you choose nums[i-1], the temporary scheme temp1
dp[i][x] = judge(temp1, temp2) ? temp1 : temp2;
- Boundary
guaranteei,x>=1
, need to initialize row 0, column 0 is empty scheme - The processing sequence
involves upper left and upper, and the processing sequence is from top to bottom and from left to right.
class Solution {
public:
struct selection{
vector<int> n1, n2;
};
vector<int> maxNumber(vector<int>& nums1, vector<int>& nums2, int k) {
int len1=nums1.size(), len2=nums2.size(), len=len1+len2;
vector<int> ans;
if(len==0) return ans;
selection dp[len+1][k+1];
//填表
for(int i=1; i<=len; i++){
for(int x=1; x<=k; x++){
//若选nums[i-1]
selection temp1 = dp[i-1][x-1];
if(i-1<len1) temp1.n1.emplace_back(nums1[i-1]);
else temp1.n2.emplace_back(nums2[i-1-len1]);
//若不选nums[i-1]
selection temp2 = dp[i-1][x];
//判断temp1和temp2谁大
dp[i][x] = judge(temp1, temp2) ? temp1 : temp2;
}
}
create(dp[len][k], ans);
return ans;
}
bool judge(selection &a, selection &b){
//判断a是否比b更好
vector<int> an, bn;
create(a, an);
create(b, bn);
int sa=an.size(), sb=bn.size();
if(sa>sb) return true;
else if(sa<sb) return false;
else{
for(int i=0; i<sa; i++){
if(an[i]>bn[i]) return true;
else if(an[i]<bn[i]) return false;
}
return false;
}
}
void create(selection &a, vector<int> &an){
int t1=a.n1.size(), t2=a.n2.size(), p1=0, p2=0;
while(p1<t1 && p2<t2){
bool out = true;
int i;
for(i=0; p1+i<t1 && p2+i<t2; i++){
if(a.n1[p1+i]!=a.n2[p2+i]){
if(a.n1[p1+i]>a.n2[p2+i]) an.emplace_back(a.n1[p1++]);
else an.emplace_back(a.n2[p2++]);
out = false;
break;
}
}
if(out){
if(p1+i>=t1) an.emplace_back(a.n2[p2++]);
else an.emplace_back(a.n1[p1++]);
}
}
while(p1<t1) an.emplace_back(a.n1[p1++]);
while(p2<t2) an.emplace_back(a.n2[p2++]);
return;
}
};
Solution: There is a strategy to choose the number
The scheme that constitutes the maximum number must be the maximum number under the same conditions in nums1 and nums2.
Enumerate nums1 and 2 to take several numbers.
ac code:
class Solution {
public:
vector<int> maxNumber(vector<int>& nums1, vector<int>& nums2, int k) {
int len1=nums1.size(), len2=nums2.size();
vector<int> ans;
for(int n1=0; n1<=min(len1, k); n1++){
int n2 = k - n1;
if(n2>len2) continue;
vector<int> se1, se2, res;
getNumbers(nums1, se1, n1);
getNumbers(nums2, se2, n2);
create(se1, se2, res);
if(judge(res, ans)) ans = res;
}
return ans;
}
void getNumbers(vector<int>& nums, vector<int>& se, int k){
vector<int>::iterator s = nums.begin();
vector<int>::iterator e = nums.end() - k + 1;
while(k--){
vector<int>::iterator it = max_element(s, e);
se.emplace_back(*it);
s = it + 1;
e++;
}
return;
}
void create(vector<int>& a, vector<int>& b, vector<int>& res){
int t1=a.size(), t2=b.size(), p1=0, p2=0;
while(p1<t1 && p2<t2){
bool out = true;
int i;
for(i=0; p1+i<t1 && p2+i<t2; i++){
if(a[p1+i]!=b[p2+i]){
if(a[p1+i]>b[p2+i]) res.emplace_back(a[p1++]);
else res.emplace_back(b[p2++]);
out = false;
break;
}
}
if(out){
if(p1+i>=t1) res.emplace_back(b[p2++]);
else res.emplace_back(a[p1++]);
}
}
while(p1<t1) res.emplace_back(a[p1++]);
while(p2<t2) res.emplace_back(b[p2++]);
return;
}
bool judge(vector<int>& a, vector<int>& b){
int sa=a.size(), sb=b.size();
if(sa>sb) return true;
else if(sa<sb) return false;
else{
for(int i=0; i<sa; i++){
if(a[i]>b[i]) return true;
else if(a[i]<b[i]) return false;
}
return false;
}
}
};