**大数和中的极值位距离 **
自己实现的算法是用的暴力解出来 感觉效率比较低 期望有大佬能给出更好的做法
问题描述
在日常的编程中,我们经常会遇到需要处理大数字的情况。比如计算两个非常大的整数的和,或是寻找两个大数之间的最大差值等。这种场景下,我们无法简单地使用 Java 或其他编程语言中的基本数据类型,因为它们都有存储范围的限制。相反,我们需要使用特殊的数据结构和算法来解决这类问题。
本题就是一个典型的大数处理问题。给定两个由数字字符组成的超大字符串,需要求出它们相加后得到的新字符串中,最大数和最小数之间的位数差距。如果结果中所有数字都相同,则差距为0。如果存在多个符合最大或最小条件的数字,应该选择最小的位置差。
例如,字符串 "111" 和 "222" 相加得到 "333",所有数字相同,因此位数差为0。另一个例子,"111" 和 "34" 相加得到 "145",其中最大数是 '5' 位于第3位,最小数是 '1' 位于第1位,它们之间的位差为1。
解题思路
要解决这个问题,我们需要分为几个步骤:
-
首先实现一个能够处理大数相加的函数。由于Java中的基本数据类型无法存储这么大的数字,我们需要使用字符串来表示这些数字,并逐位相加来得到最终结果。
-
在得到相加结果之后,我们需要遍历这个字符串,找出其中的最大值和最小值。在遍历的同时,我们还需要记录下最大值和最小值出现的位置。
-
最后,我们需要比较最大值和最小值的位置差,并返回最小的位置差。如果所有数字都相同,则返回0。
在实现上述步骤时,需要注意以下几个关键点:
-
大数相加的实现:由于输入的数字可能非常大,我们无法使用Java中的基本数据类型来存储和计算它们。取而代之的是,我们需要使用字符串来表示这些数字,并逐位相加。这种方式虽然比直接使用基本数据类型要慢一些,但它可以处理任意大小的数字。
-
最大值和最小值的查找:在得到相加结果之后,我们需要遍历这个字符串,找出其中的最大值和最小值。同时,我们还需要记录下它们出现的位置,因为题目要求返回最小的位置差。
-
多个最大值或最小值的情况:如果存在多个符合最大或最小条件的数字,我们应该选择最小的位置差。因此,在记录最大值和最小值的位置时,需要使用列表来存储所有符合条件的位置。
通过这三个步骤,我们就可以完整地解决这个问题了。下面让我们看看具体的代码实现。
代码实现
在代码实现部分,我们首先定义了一个 addStrings() 函数,用于实现两个大数字字符串的相加操作。这个函数使用了一个 StringBuilder 来逐位相加并存储结果。
接下来,我们实现了 solution() 函数,它是本题的主要解决方案。在这个函数中,我们先调用 addStrings() 函数得到相加结果,然后遍历这个字符串,找出最大值和最小值以及它们出现的位置。
最后,我们比较最大值和最小值的位置差,并返回最小的位置差。如果所有数字都相同,则返回0。
通过这种方式,我们就成功地解决了这个大数相加的问题,并找出了最大值和最小值之间的位置差。
import java.util.*;
public class Main {
// public static int solution(String string1, String string2) {
// // Please write your code here
// return -2;
// }
public static int solution(String string1, String string2) {
String s=addStrings(string1,string2);
int min=10,max=-1;
int len = s.length();
for(int i = 0; i< len; i++) {
min = Math.min(min, s.charAt(i) - '0');
max = Math.max(max, s.charAt(i) - '0');
}
if(min==max)return 0;
ArrayList<Integer> min_list=new ArrayList<Integer>();
ArrayList<Integer> max_list=new ArrayList<Integer>();
for(int i = 0; i< len; i++){
if(s.charAt(i)-'0'==min)
min_list.add(i);
if (s.charAt(i)-'0'==max)
max_list.add(i);
}
int ans=len;
for(int i=0;i<min_list.size();i++)
for(int j=0;j<max_list.size();j++)
ans=Math.min(Math.abs(min_list.get(i)-max_list.get(j))-1,ans);
return ans;
}
private static String addStrings(String s1, String s2) {
StringBuilder sb = new StringBuilder();
int i = s1.length() - 1, j = s2.length() - 1;
int carry = 0;
while (i >= 0 || j >= 0) {
int sum = carry;
if (i >= 0) sum += s1.charAt(i--) - '0';
if (j >= 0) sum += s2.charAt(j--) - '0';
sb.append(sum % 10);
carry = sum / 10;
}
if (carry != 0) sb.append(carry);
return sb.reverse().toString();
}
public static void main(String[] args) {
// You can add more test cases here
System.out.println(solution("111", "222") == 0);
System.out.println(solution("111", "34") == 1);
System.out.println(solution("5976762424003073", "6301027308640389") == 6);
System.out.println(solution("2222222222222222222222","1")==0);
}
}
复杂度分析
让我们来分析一下这个解决方案的时间复杂度和空间复杂度:
-
时间复杂度:
addStrings()函数的时间复杂度为 O(m+n),其中 m 和 n 分别是两个输入字符串的长度。solution()函数中的遍历操作需要 O(m+n)的时间复杂度,其中 m+n 是最终相加结果的长度。- 最后比较最大值和最小值位置差的操作需要 O(mn)的时间复杂度,其中 m 和 n 分别是最大值和最小值出现的位置个数。
- 因此,整个解决方案的总时间复杂度为 O(m+n+mn)。
-
空间复杂度:
addStrings()函数需要使用一个StringBuilder来存储相加结果,因此空间复杂度为 O(m+n)。solution()函数中需要使用两个列表来存储最大值和最小值的位置,因此空间复杂度为 O(m+n)。- 因此,整个解决方案的总空间复杂度为 O(m+n)。
总的来说,这个解决方案的时间复杂度和空间复杂度都是可以接受的,能够很好地处理大数相加的问题。
结论
在日常编程中,我们经常会遇到需要处理大数字的场景。本文介绍了一个典型的大数相加问题,并提供了一种有效的解决方案。通过实现一个大数相加的函数,再找出最大值和最小值的位置,最后计算它们之间的位置差,我们就可以很好地解决这个问题。
这种方式不仅可以处理任意大小的数字,而且时间复杂度和空间复杂度也是可以接受的。希望通过本文的讲解,大家能够学会如何应对大数相关的编程问题,并在实际开发中灵活应用这些技巧。