给一组数,可以重复组合,组成一个比n刚好小的数字

字节给的这个算法题,也不知道LeetCode上有没有这个题,当时有动态规划的想法,但是没做出来(挂了),之后又研究了一下,下面是我的解题代码逻辑,

题目:

给你一个n和一个数字的数组,比如n=23121,数组A={2,4,9},当然保证数组A中都是个位数,并且没有重复的,没说数组A有序,我这默认有序,结果得到一个数22999,就是数组A拼出来的一个刚好比n小的数。

解题思路

正常的动态规划用到的二维数组,额外需要一个二维boolean数组来做辅助

初始化图(一个二维数组,一个Boolean二维辅助图)

左边是n和数组A的二维数组,右边是一个辅助二维数组图,初始化都为false,后续的只要说是二维数组就是指左边的图,辅助图就是右边的图
在这里插入图片描述

二维数组填数的逻辑

1、首先介绍二维辅助图为true和false的情况
  1. 当为true的情况: 代表二维数组同一行后一位的数,直接填y[行],当前的辅助图位置也要填true,为同行后一个数直接填y[行]做前置条件
  2. 当为false的情况: 代表二维数组同一行后一位的数需要进行下面逻辑判断
2、同行前一位为false的情况,如何填当前二维数组中的数

当前y[行]的值和当前x[列]的值做比较

  1. 当y[行] == x[列] ,当前位置填y[行],辅助图不用变
  2. 当y[行] < x[列] ,当前位置填y[行],辅助图的当前位置填true
  3. 当y[行] > x[列] ,当前位置填在二维数组行-1,列相同位置的数,辅助图也按这个规则来
3、第一行第一列单独计算

上面比较的前提是二维数组中第一行第一列已经计算出来了

第一行填数的逻辑:

  1. 当辅助图同一行前一列为true时,直接填y[0],排除(0,0)这个位置的数,因为它没有前一列
  2. 当y[0] == x[列] ,当前位置填y[0],辅助图不用变
  3. 当y[0] < x[列] ,当前位置填y[0],辅助图的当前位置填true
  4. 当y[0] > x[列] ,给二位数组中(0,0)的赋值0,并且辅助图(0,0)的赋值true。之后重置遍历第一行,从第一行第二列开始重新给二位数组赋值

这里的第四步是为了防止后续的某一列值比数组A中任何值都小(并且前面的值都是刚好相等的情况),举个例子:n=21202 数组A{2},

以n=23121 数组A={2,4,9}为例,第一行计算完应该是下面的图
在这里插入图片描述

第一列填数的逻辑

这里是从第二行第一列开始,因为(0,0)已经在第一行填完了

  1. 当y[列] == x[0] ,当前位置填y[列],辅助图不用变
  2. 当y[0] < x[列] ,当前位置填y[列],辅助图的当前位置填true
  3. 当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

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值