刷题:贪心——小U的数字插入问题

121 阅读4分钟

刷题:贪心——小U的数字插入问题

Created: 2024年11月3日 12:52 Class: 刷题

题目解析

题目

问题描述

小U手中有两个数字 a 和 b。第一个数字是一个任意的正整数,而第二个数字是一个非负整数。她的任务是将第二个数字 b 插入到第一个数字 a 的某个位置,以形成一个最大的可能数字。

你需要帮助小U找到这个插入位置,输出插入后的最大结果。


测试样例

样例1:

输入:a = 76543, b = 4

输出:765443

样例2:

输入:a = 1, b = 0

输出:10

样例3:

输入:a = 44, b = 5

输出:544

样例4:

输入:a = 666, b = 6

输出:6666

解析

这里的题目描述不是很清楚:

  • b可以是多位数的整数
  • 插入时,b是以整体为单位插入的。比如:a=121, b = 15 ⇒ res = 15121,而不是51121.

思路

总体步骤就是:

  1. 把int转为ArrayList,方便插入。
  2. 遍历a的每一位,判断b能不能插进去。
    1. 一次性插入结束
  3. 如果中间位次没有插进去,就插到最后即可。

获得每一位的值

很简单,利用除和余这两个算数操作即可:

  • / 可以获得下一次循环的整数
  • % 可以获得这个位上的值

以123为例,看一下计算步骤

  1. a = 123 a % 10 = 3 a / 10 = 12
  2. a = 12 a % 10 = 2 a / 10 = 1
  3. a = 1 a % 10 = 1 a / 10 = 0
  4. a = 0 结束

java实现代码如下:

public static ArrayList<Integer> get(int a) {
    ArrayList<Integer> res = new ArrayList<>();
    if (a == 0) {
        res.add(0);
    }
    while (a > 0) {
        res.add(0, a % 10);
        a = a / 10;
    }
    return res;
}

至于为什么用ArrayList保存,是为了方便直接在a上插入。如果是数组 int[] 的话,插入还得把后面的值挪一下,怪麻烦的。

判断是否能插入

这里需要注意到非常重要的一点:b是整体插入的,且b可能是多位的。

我举几个例子,就比较好明白,要注意那些问题了

  • 第一个例子:a = 12, b = 15

    我们不是要遍历一遍a的每一位嘛。好,当a[0] = 1,b[0] 也=1时,能不能插入?不好说,所以要考虑下一位的大小。a[1] = 2, b[1] = 5,能不能?当然可以,你说1215大还是1512大?当然是1512啦。

  • 再来一个:a = 3123, b = 12

    当a[0] = 3,b[0] =1时,当然不插入。a[1] = 1, b[0] = 1时,不好说,考虑下一位。a[2] = 2, b[1] = 2,能不能?不能!你说是312123大还是312312大?当然是312312啦,所以还得判断a的下一位a[2] = 2,b[0] = 1,不插入,a[3]也不插入。那就是312312是最大的。

    好!这个例子太棒了!

这里我的思路是,考虑什么时候不能插入:

  • 当b的所有位等于a的与之相对应位时,不插。
  • 当a的对应位大于b对应的位时,不用考虑b后面的了,直接不插即可

感觉直接看代码会比较好理解一点,代码实现为:

public static boolean isCan(ArrayList<Integer> a_list, int i, ArrayList<Integer> b_list) {
    int bi = 0;
    boolean isequal = true;
    for (; i < a_list.size() && bi < b_list.size(); i++, bi++) {
        if (b_list.get(bi) < a_list.get(i)) {
            return false;
        } else if (b_list.get(bi) > a_list.get(i)) {
            isequal = false;
        }
    }
    return !isequal;
}

最后插入

测试样例中给了一个样例:a = 1, b = 0

遍历完a的所有位之后,b还没插入。那就在全放在a的最后吧。

好!所有需要注意的都注意完了,那就写代码吧。

代码

import java.util.*;

public class Main {
    public static ArrayList<Integer> get(int a) {
        ArrayList<Integer> res = new ArrayList<>();
        if (a == 0) {
            res.add(0);
        }
        while (a > 0) {
            res.add(0, a % 10);
            a = a / 10;
        }
        return res;
    }

    public static boolean isCan(ArrayList<Integer> a_list, int i, ArrayList<Integer> b_list) {
        int bi = 0;
        boolean isequal = true;
        for (; i < a_list.size() && bi < b_list.size(); i++, bi++) {
            if (b_list.get(bi) < a_list.get(i)) {
                return false;
            } else if (b_list.get(bi) > a_list.get(i)) {
                isequal = false;
            }
        }
        return !isequal;
    }

    public static int solution(int a, int b) {
        ArrayList<Integer> a_list = get(a);
        ArrayList<Integer> b_list = get(b);
        // b_list.sort(Comparator.reverseOrder());
        // write code here
        int bp = 0;
        for (int i = 0; i < a_list.size(); i++) {
            if (isCan(a_list, i, b_list)) {
                for (; bp < b_list.size(); bp++) {
                    a_list.add(i, b_list.get(bp));
                    i++;
                }
                break;
            }
        }
        for (; bp < b_list.size(); bp++) {
            a_list.add(b_list.get(bp));
        }

        StringBuilder sb = new StringBuilder();
        for (int i : a_list) {
            sb.append(i + "");
        }
        return Integer.parseInt(sb.toString());
    }

    public static void main(String[] args) {
        System.out.println(solution(76543, 4) == 765443);
        System.out.println(solution(1, 0) == 10);
        System.out.println(solution(44, 5) == 544);
        System.out.println(solution(666, 6) == 6666);
        System.out.println(solution(9, 15) == 915);
        System.out.println(solution(17, 1) == 171);
        System.out.println(solution(12, 15) == 1512);
    }
}

总结

提交了好几次,才考虑全。要是acm模式,分得扣成啥样啊。。。

之后还是尽量多想想其他测试样例,减少提交次数吧。

写笔记的时候忽然想到是不是跟kmp类似,但是不是,因为每一位都需要判断是否插入,所以a的位数是不能跳过的。