给定长度分别为 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]
链接:https://leetcode-cn.com/problems/create-maximum-number
看到这道题,原以为很简单,依次选,选大的就好啊,但是当两边一样大的时候,就纠结了,然后用了一个方法,超时。有用了一个方法,内存超了。
最后突然有了灵感,如果选500个数,那就可能0+500,1+499,2+498…
而这时候只要考虑两个小算法就行,第一个就是在数组内找到指定长度的最大值。第二个就是拼接两个值成最大值
答案:
public int[] maxNumber(int[] nums1, int[] nums2, int k) {
int[] ans = null;
for (int i = 0; i <= k; i++) {
if (i == 1) {
System.out.println();
}
if (nums2.length < k - i || i > nums1.length) {
continue;
}
int[] ans1 = getF(nums1, i);
int[] ans2 = getF(nums2, k - i);
int[] anss = getFF(ans1, ans2);
if (ans == null || lager(anss, ans)) {
ans = anss;
}
}
return ans;
}
//拼接两个数组
private int[] getFF(int[] ans1, int[] ans2) {
int[] ans = new int[ans1.length + ans2.length];
int key = 0;
for (int i = 0, j = 0; i < ans1.length || j < ans2.length; ) {
if (j == ans2.length) {
ans[key++] = ans1[i++];
} else if (i == ans1.length) {
ans[key++] = ans2[j++];
} else {
if (lager(ans1, ans2, i, j)) {
ans[key++] = ans1[i++];
} else {
ans[key++] = ans2[j++];
}
}
}
return ans;
}
//nums1数组中最大的num位值
private int[] getF(int[] nums1, int num) {
int[] ans = new int[num];
if (num == 0) {
return ans;
}
int key = -1;
for (int i = 0; i < nums1.length; i++) {
if (key + 1 + nums1.length - i == num) {
ans[++key] = nums1[i];
continue;
}
if (key == -1 || nums1[i] <= ans[key]) {
if (key == num - 1) {
continue;
}
ans[++key] = nums1[i];
} else {
key--;
i--;
}
}
return ans;
}
private boolean lager(int[] an1, int[] an2) {
for (int i = 0; i < an1.length; i++) {
if (an1[i] > an2[i]) {
return true;
} else if (an1[i] < an2[i]) {
return false;
}
}
return false;
}
private boolean lager(int[] an1, int[] an2, int sta1, int sta2) {
int i = 0;
for (; i + sta1 < an1.length && i + sta2 < an2.length; i++) {
if (an1[i + sta1] > an2[i + sta2]) {
return true;
} else if (an1[i + sta1] < an2[i + sta2]) {
return false;
}
}
if (i + sta2 == an2.length) {
return true;
}
return false;
}
附加:
超时算法:
class Solution {
int[] ans;
public int[] maxNumber(int[] nums1, int[] nums2, int k) {
ans = new int[k];
maxNum(nums1, 0, nums2, 0, 0, k, false);
return ans;
}
private void maxNum(int[] nums1, int sta1, int[] nums2, int sta2, int key, int k, boolean canH) {
if (key == k) {
return;
}
if (canH) {
ans[key] = 0;
}
int temp1 = ans[key] - 1;
int st1 = -1;
for (int i = sta1; i < nums1.length && i <= (nums1.length + nums2.length) - (sta2 + (k - key)); i++) {
if (nums1[i] > temp1) {
temp1 = nums1[i];
st1 = i;
}
}
int st2 = -1;
int temp2 = ans[key] - 1;
for (int i = sta2; i < nums2.length && i <= (nums1.length + nums2.length) - (sta1 + (k - key)); i++) {
if (nums2[i] > temp2) {
temp2 = nums2[i];
st2 = i;
}
}
if (temp1 > temp2) {
if (temp1 < ans[key]) {
} else if (temp1 == ans[key]) {
maxNum(nums1, st1 + 1, nums2, sta2, key + 1, k, false | canH);
} else {
ans[key] = temp1;
maxNum(nums1, st1 + 1, nums2, sta2, key + 1, k, true);
}
return;
}
if (temp1 < temp2) {
if (temp2 < ans[key]) {
} else if (temp2 == ans[key]) {
maxNum(nums1, sta1, nums2, st2 + 1, key + 1, k, false | canH);
} else {
ans[key] = temp2;
maxNum(nums1, sta1, nums2, st2 + 1, key + 1, k, true);
}
return;
}
if (temp1 < ans[key]) {
} else if (temp1 == ans[key]) {
maxNum(nums1, st1 + 1, nums2, sta2, key + 1, k, false | canH);
} else {
ans[key] = temp1;
maxNum(nums1, st1 + 1, nums2, sta2, key + 1, k, true);
}
canH = false;
if (temp2 < ans[key]) {
} else if (temp2 == ans[key]) {
maxNum(nums1, sta1, nums2, st2 + 1, key + 1, k, false | canH);
} else {
ans[key] = temp2;
maxNum(nums1, sta1, nums2, st2 + 1, key + 1, k, true);
}
}
}
超内存算法:
class Solution {
int[] ans;
public int[] maxNumber(int[] nums1, int[] nums2, int k) {
bbb = new boolean[nums1.length + 1][nums2.length + 1];
anss = new int[nums1.length + 1][nums2.length + 1][k];
ans = new int[k];
ans = maxNum(nums1, 0, nums2, 0, 0, k);
return ans;
}
boolean[][] bbb;
int[][][] anss;
private int[] maxNum(int[] nums1, int sta1, int[] nums2, int sta2, int key, int k) {
if (key == k) {
return new int[0];
}
if (bbb[sta1][sta2]) {
return anss[sta1][sta2];
}
bbb[sta1][sta2] = true;
int temp1 = -1;
int st1 = -1;
for (int i = sta1; i < nums1.length && i <= (nums1.length + nums2.length) - (sta2 + (k - key)); i++) {
if (nums1[i] > temp1) {
temp1 = nums1[i];
st1 = i;
}
}
int st2 = -1;
int temp2 = -1;
for (int i = sta2; i < nums2.length && i <= (nums1.length + nums2.length) - (sta1 + (k - key)); i++) {
if (nums2[i] > temp2) {
temp2 = nums2[i];
st2 = i;
}
}
if (temp1 > temp2) {
int[] an = maxNum(nums1, st1 + 1, nums2, sta2, key + 1, k);
int[] ann = new int[an.length + 1];
ann[0] = temp1;
for (int i = 0; i < an.length; i++) {
ann[i + 1] = an[i];
}
anss[sta1][sta2] = ann;
return ann;
}
if (temp1 < temp2) {
int[] an = maxNum(nums1, sta1, nums2, st2 + 1, key + 1, k);
int[] ann = new int[an.length + 1];
ann[0] = temp2;
for (int i = 0; i < an.length; i++) {
ann[i + 1] = an[i];
}
anss[sta1][sta2] = ann;
return ann;
}
int[] an1 = maxNum(nums1, st1 + 1, nums2, sta2, key + 1, k);
int[] an2 = maxNum(nums1, sta1, nums2, st2 + 1, key + 1, k);
if (lager(an1, an2)) {
int[] ann = new int[an1.length + 1];
ann[0] = temp1;
for (int i = 0; i < an1.length; i++) {
ann[i + 1] = an1[i];
}
anss[sta1][sta2] = ann;
return ann;
} else {
int[] ann = new int[an2.length + 1];
ann[0] = temp1;
for (int i = 0; i < an2.length; i++) {
ann[i + 1] = an2[i];
}
anss[sta1][sta2] = ann;
return ann;
}
}
private boolean lager(int[] an1, int[] an2) {
for (int i =0; i < an1.length; i++) {
if (an1[i] > an2[i]) {
return true;
} else if (an1[i] < an2[i]) {
return false;
}
}
return false;
}
}