字节给的这个算法题,也不知道LeetCode上有没有这个题,当时有动态规划的想法,但是没做出来(挂了),之后又研究了一下,下面是我的解题代码逻辑,
文章目录
题目:
给你一个n和一个数字的数组,比如n=23121,数组A={2,4,9},当然保证数组A中都是个位数,并且没有重复的,没说数组A有序,我这默认有序,结果得到一个数22999,就是数组A拼出来的一个刚好比n小的数。
解题思路
正常的动态规划用到的二维数组,额外需要一个二维boolean数组来做辅助
初始化图(一个二维数组,一个Boolean二维辅助图)
左边是n和数组A的二维数组,右边是一个辅助二维数组图,初始化都为false,后续的只要说是二维数组就是指左边的图,辅助图就是右边的图
二维数组填数的逻辑
1、首先介绍二维辅助图为true和false的情况
- 当为true的情况: 代表二维数组同一行后一位的数,直接填y[行],当前的辅助图位置也要填true,为同行后一个数直接填y[行]做前置条件
- 当为false的情况: 代表二维数组同一行后一位的数需要进行下面逻辑判断
2、同行前一位为false的情况,如何填当前二维数组中的数
当前y[行]的值和当前x[列]的值做比较
- 当y[行] == x[列] ,当前位置填y[行],辅助图不用变
- 当y[行] < x[列] ,当前位置填y[行],辅助图的当前位置填true
- 当y[行] > x[列] ,当前位置填在二维数组行-1,列相同位置的数,辅助图也按这个规则来
3、第一行第一列单独计算
上面比较的前提是二维数组中第一行第一列已经计算出来了
第一行填数的逻辑:
- 当辅助图同一行前一列为true时,直接填y[0],排除(0,0)这个位置的数,因为它没有前一列,
- 当y[0] == x[列] ,当前位置填y[0],辅助图不用变
- 当y[0] < x[列] ,当前位置填y[0],辅助图的当前位置填true
- 当y[0] > x[列] ,给二位数组中(0,0)的赋值0,并且辅助图(0,0)的赋值true。之后重置遍历第一行,从第一行第二列开始重新给二位数组赋值
这里的第四步是为了防止后续的某一列值比数组A中任何值都小(并且前面的值都是刚好相等的情况),举个例子:n=21202 数组A{2},
以n=23121 数组A={2,4,9}为例,第一行计算完应该是下面的图
第一列填数的逻辑
这里是从第二行第一列开始,因为(0,0)已经在第一行填完了
- 当y[列] == x[0] ,当前位置填y[列],辅助图不用变
- 当y[0] < x[列] ,当前位置填y[列],辅助图的当前位置填true
- 当y[0] > x[列] ,当前位置填在二维数组行-1,列相同位置的数,辅助图也按这个规则来
以n=23121 数组A={2,4,9}为例,第一列计算完应该是下面的图
4、最后的结果
把最后最后一行的数组拼成一个数字,就是22999
代码:
public static void main(String[] args) {
main main = new main();
int[]x= new int[]{2,3,1,2,1};
int[]y= new int[]{2,4,9};
main.start(x,y);
}
public void start(int[]x,int[]y){
int [][]b=new int[3][x.length];
boolean [][]flag = new boolean[y.length][x.length];
for (int i = 0; i <x.length ; i++) {
if (i>0&&flag[0][i-1]) {
b[0][i]=y[0];
flag[0][i]=true;
continue;
}
if(x[i]==y[0]){
b[0][i]=y[0];
continue;
}
if(y[0]<x[i]){
b[0][i]=y[0];
flag[0][i]=true;
continue;
}
if(y[0]>x[i]){
i=0;
b[0][0]=0;
flag[0][0]=true;
}
}
System.out.println(Arrays.deepToString(flag));
System.out.println(Arrays.deepToString(b));
for (int i = 1; i <y.length; i++) {
if(y[i]==x[0]){
b[i][0]=y[i];
continue;
}
if(y[i]<x[0]){
b[i][0]=y[i];
flag[i][0]=true;
continue;
}
if(y[i]>x[0]){
b[i][0]=b[i-1][0];
flag[i][0]=flag[i-1][0];
}
}
System.out.println(Arrays.deepToString(flag));
System.out.println(Arrays.deepToString(b));
for (int i = 1; i <y.length ; i++) {
for (int j = 1; j <x.length; j++) {
if(flag[i][j-1]){
b[i][j]=y[i];
flag[i][j]=true;
continue;
}
if (y[i]==x[j]) {
b[i][j]=y[i];
continue;
}
if(y[i]<x[j]){
b[i][j]=y[i];
flag[i][j]=true;
continue;
}
if (y[i]>x[j]) {
b[i][j]=b[i-1][j];
flag[i][j]=flag[i-1][j];
}
}
}
System.out.println(Arrays.deepToString(flag));
System.out.println(Arrays.deepToString(b));
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i <x.length; i++) {
stringBuilder.append(b[y.length-1][i]);
}
System.out.println(Integer.parseInt(stringBuilder.toString()));
}
目前的测试用例
n=23121, A={2,4,9} 结果:22999
n=21121, A={2,4,9} 结果: 9999
n=23121 , A={0,9,4} 结果:9999
n=0, A={1} 结果:0