刷题:贪心——小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.
思路
总体步骤就是:
- 把int转为ArrayList,方便插入。
- 遍历a的每一位,判断b能不能插进去。
- 一次性插入结束
- 如果中间位次没有插进去,就插到最后即可。
获得每一位的值
很简单,利用除和余这两个算数操作即可:
- 除
/可以获得下一次循环的整数 - 余
%可以获得这个位上的值
以123为例,看一下计算步骤
- a = 123 a % 10 = 3 a / 10 = 12
- a = 12 a % 10 = 2 a / 10 = 1
- a = 1 a % 10 = 1 a / 10 = 0
- 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的位数是不能跳过的。