问题描述
小R面对一个问题,她有两个由数字字符组成的超大字符串数,需要求出这两个数相加后得到的字符串数中的最大数和最小数之间的位数差距。如果结果中所有数字都相同,则差距为 0。如果存在多个符合最大或最小条件的数,应该选择最小的位置差。
例如,字符串数 "111" 和 "222" 相加得到 "333",所有数字相同,因此位数差为 0。另一例子,字符串数 "111" 和 "34" 相加得到 "145",其中最大数是 '5' 位于第 3 位,最小数是 '1' 位于第 1 位,他们之间的位差为 1。
测试样例
样例1:
输入:
string1 = "111",string2 = "222"
输出:0
样例2:
输入:
string1 = "111",string2 = "34"
输出:1
样例3:
输入:
string1 = "999",string2 = "1"
输出:0
样例4:
输入:
string1 = "525",string2 = "474"
输出:0
思路分析
本题首先需要进行一个大数相加,得到两个大数之和。接着需要找到和中最大数和最小数之间的最小距离。直接遍历数组,将和中所有数的索引计入一个哈希表中。进而得到最大值和最小值,如果两值相等则返回0。如果不相等则遍历最大值和最小值的索引数组。因为索引数组是递增的,我们可以使用双指针进行遍历,最终得到两个数组差的绝对值的最小值。
代码分析
1. 字符串转换和反转
笨人习惯使用数组进行大数相加
List<Integer> arr1 = new ArrayList<>();
List<Integer> arr2 = new ArrayList<>();
for (int i = 0; i < string1.length(); i++) arr1.add(string1.charAt(i) - '0');
for (int i = 0; i < string2.length(); i++) arr2.add(string2.charAt(i) - '0');
Collections.reverse(arr1);
Collections.reverse(arr2);
- 字符串转换:将输入的两个字符串
string1和string2转换为整数列表arr1和arr2。 - 反转列表:反转这两个列表,以便从低位到高位进行加法运算。
2. 大数加法
List<Integer> res = new ArrayList<>();
int t = 0;
for (int i = 0; i < arr1.size() || i < arr2.size(); i++) {
if (i < arr1.size()) t += arr1.get(i);
if (i < arr2.size()) t += arr2.get(i);
res.add(t % 10);
t /= 10;
}
if (t == 1) res.add(t);
- 逐位相加:从低位到高位逐位相加,
t用于处理进位。 - 处理进位:将当前位的和模10加入结果列表
res,并将进位t除以10。 - 最后进位处理:如果最高位有进位(
t == 1),则将其加入结果列表。
3. 查找最大和最小数字及其位置
Map<Integer, List<Integer>> hash = new HashMap<>();
int minV = 10;
int maxV = -1;
for (int i = 0; i < res.size(); i++) {
if (res.get(i) > maxV) maxV = res.get(i);
if (res.get(i) < minV) minV = res.get(i);
List<Integer> temp = hash.getOrDefault(res.get(i), new ArrayList<>());
temp.add(i);
hash.put(res.get(i), temp);
}
- 查找最大和最小数字:遍历结果列表
res,找到最大数字maxV和最小数字minV。 - 记录位置:使用哈希表
hash记录每个数字出现的位置。
4. 计算位数差距
if (minV == maxV) return 0;
int i = 0, j = 0;
int minDiff = Integer.MAX_VALUE;
arr1 = hash.get(minV);
arr2 = hash.get(maxV);
while (i < arr1.size() && j < arr2.size()) {
int diff = Math.abs(arr1.get(i) - arr2.get(j));
if (diff < minDiff) {
minDiff = diff;
}
if (arr1.get(i) < arr2.get(j)) {
i++;
} else {
j++;
}
}
return minDiff - 1;
- 相同数字处理:如果最大和最小数字相同,直接返回0。
- 计算最小位数差距:使用双指针法,遍历最小数字和最大数字的位置列表,计算它们之间的最小位数差距。
- 返回结果:返回最小位数差距减1(因为题目要求的是位数差距,而不是索引差距)。
总结
本题主要设计字符串转换、大数加法、双指针的知识点。