高精度运算

高精度

1. 高精度原理

原理

  • 利用vector对很大的数据(long long没法存下,一般用string存储)进行计算,可以分为高精度加减乘除,对于给定A、B(位数最多为 1 0 6 10^6 106),给定bb<=1000),求:(1)A+B;(2)A-B;(3)A*b;(4)A/b

  • 具体每个细节可以参考下面的题目。

2. AcWing上的高精度题目

AcWing 791. 高精度加法

问题描述

  • 问题链接:AcWing 791. 高精度加法

    高精度运算_第1张图片

分析

  • 首先就要考虑数据的存储方式。因为数据非常大,因此不能使用long long或者其他类型表示,否则会溢出。我们可以首先将数据读入字符串中,然后存入数组中(C++中对应vectorJava中对应List),因为我们的计算都是从个位开始的,因此数据的最低位存储在索引为0的位置。

  • 假设两个需要相加的数据存储到了A、B中(A、Bvector或者List),我们按照小学的加法运算将结果存储到另一个数组C中即可,计算过程中使用t表示进位。

  • 最后将C中的每个数据按照索引由大到小数据即是结果。

  • 另外可以采用压位的写法,即在加法中将9个比特位存放到一个int中,这样比较节省空间,同时也能提升运行效率。

代码

  • C++
#include 
#include 

using namespace std;

vector<int> add(vector<int> &A, vector<int> &B) {
     
    
    vector<int> C;
    for (int i = 0, t = 0; i < A.size() || i < B.size() || t; i++) {
       // t:进位
        if (i < A.size()) t += A[i];
        if (i < B.size()) t += B[i];
        C.push_back(t % 10);
        t /= 10;
    }
    
    return C;
}

int main() {
     
    
    string a, b;
    cin >> a >> b;
    
    vector<int> A, B;
    for (int i = a.size() - 1; i >= 0; i--) A.push_back(a[i] - '0');
    for (int i = b.size() - 1; i >= 0; i--) B.push_back(b[i] - '0');
    
    vector<int> C = add(A, B);
    
    for (int i = C.size() - 1; i >= 0; i--)
        printf("%d", C[i]);
    
    return 0;
}
// 压位写法:压9位
#include 
#include 

using namespace std;

const int base = 1000000000;

vector<int> add(vector<int> &A, vector<int> &B) {
     
    
    vector<int> C;
    for (int i = 0, t = 0; i < A.size() || i < B.size() || t; i++) {
     
        if (i < A.size()) t += A[i];
        if (i < B.size()) t += B[i];
        C.push_back(t % base);
        t /= base;
    }
    
    return C;
}

int main() {
     
    
    string a, b;
    cin >> a >> b;
    
    vector<int> A, B;
    for (int i = a.size() - 1, s = 0, j = 0, t = 1; i >= 0; i--) {
     
        s += (a[i] - '0') * t;  // 假设12345, 则s中存储的要是12345
        j++, t *= 10;
        if (j == 9 || i == 0) {
     
            A.push_back(s);
            s = 0, j = 0, t = 1;
        }
    }
    for (int i = b.size() - 1, s = 0, j = 0, t = 1; i >= 0; i--) {
     
        s += (b[i] - '0') * t;
        j++, t *= 10;
        if (j == 9 || i == 0) {
     
            B.push_back(s);
            s = 0, j = 0, t = 1;
        }
    }
    
    vector<int> C = add(A, B);
    
    cout << C.back();
    for (int i = C.size() - 2; i >= 0; i--)
        printf("%09d", C[i]);
    
    return 0;
}
  • Java
import java.util.*;

public class Main {
     
    
    private static List<Integer> add(List<Integer> A, List<Integer> B) {
     
        
        List<Integer> C = new ArrayList<>();
        int t = 0;
        for (int i = 0; i < A.size() || i < B.size(); i++) {
     
            if (i < A.size()) t += A.get(i);
            if (i < B.size()) t += B.get(i);
            C.add(t % 10);
            t /= 10;
        }
        if (t != 0) C.add(1);
        
        return C;
    }
    
    public static void main(String[] args) {
     
        // 读入数据
        Scanner scan = new Scanner(System.in);
        char[] a = scan.next().toCharArray(), b = scan.next().toCharArray();
        
        List<Integer> A = new ArrayList<>(), B = new ArrayList<>();
        for (int i = a.length - 1; i >= 0; i--) A.add(a[i] - '0');
        for (int i = b.length - 1; i >= 0; i--) B.add(b[i] - '0');
        
        List<Integer> C = add(A, B);
        
        for (int i = C.size() - 1; i >= 0; i--)
            System.out.print(C.get(i));
    }
}

AcWing 792. 高精度减法

问题描述

  • 问题链接:AcWing 792. 高精度减法

    高精度运算_第2张图片

分析

  • 和高精度加法的存储方式一致,假设两个需要相减的数据已经存储到了A、B中。这里需要保证A>=B,如果不满足的话,交换A、B,最后输出结果的时候最前面输出一个负号即可。

  • 这里的减法也是模拟小学中的减法过程,从个位开始减,最开始让借位t=0,第i位应该是A[i]-B[i]-t,如果这个数是负数,说明需要向高位借位,接一个算十个,一直这样计算每一位即可。

代码

  • C++
#include 
#include 

using namespace std;

// 如果A>=B,返回true
bool cmp(vector<int> &A, vector<int> &B) {
     
    
    if (A.size() != B.size()) return A.size() > B.size();
    for (int i = A.size() - 1; i >= 0; i--) 
        if (A[i] != B[i])
            return A[i] > B[i];
    return true;
}

vector<int> sub(vector<int> &A, vector<int> &B) {
     
    
    vector<int> C;
    for (int i = 0, t = 0; i < A.size(); i++) {
     
        t = A[i] - t;
        if (i < B.size()) t -= B[i];
        C.push_back((t + 10) % 10);
        if (t < 0) t = 1;  // 说明有借位
        else t = 0;
    }
    // 去掉前导零
    while (C.size() > 1 && C.back() == 0) C.pop_back();
    
    return C;
}

int main() {
     
    
    string a, b;
    cin >> a >> b;
    
    vector<int> A, B;
    for (int i = a.size() - 1; i >= 0; i--) A.push_back(a[i] - '0');
    for (int i = b.size() - 1; i >= 0; i--) B.push_back(b[i] - '0');
    
    vector<int> C;
    if (cmp(A, B)) {
     
        C = sub(A, B);
    } else {
     
        C = sub(B, A);
        printf("-");
    }
    
    for (int i = C.size() - 1; i >= 0; i--)
        printf("%d", C[i]);
    
    return 0;
}
  • Java
import java.util.*;

public class Main {
     
    
    // 判断是否有A >= B
    private static boolean cmp(List<Integer> A, List<Integer> B) {
     
        
        if (A.size() != B.size()) return A.size() > B.size();
        for (int i = A.size() - 1; i >= 0; i--) 
            if (A.get(i) != B.get(i))
                return A.get(i) > B.get(i);
        return true;
    }
    
    // C = A - B
    private static List<Integer> sub(List<Integer> A, List<Integer> B) {
     
        
        List<Integer> C = new ArrayList<>();
        int t = 0;
        for (int i = 0; i < A.size(); i++) {
     
            t = A.get(i) - t;
            if (i < B.size()) t -= B.get(i);
            C.add((t + 10) % 10);
            if (t < 0) t = 1;
            else t = 0;
        }
        
        while (C.size() > 1 && C.get(C.size() - 1) == 0) C.remove(C.size() - 1);
        
        return C;
    }
    
    public static void main(String[] args) {
     
        // 读入数据
        Scanner scan = new Scanner(System.in);
        char[] a = scan.next().toCharArray(), b = scan.next().toCharArray();
        List<Integer> A = new ArrayList<>(), B = new ArrayList<>();
        for (int i = a.length - 1; i >= 0; i--) A.add(a[i] - '0');
        for (int i = b.length - 1; i >= 0; i--) B.add(b[i] - '0');
        
        // 算法代码
        List<Integer> C;
        if (cmp(A, B)) C = sub(A, B);
        else {
     
            C = sub(B, A);
            System.out.print("-");
        }
        
        for (int i = C.size() - 1; i >= 0; i--) 
            System.out.print(C.get(i));
    }
}

AcWing 793. 高精度乘法

问题描述

  • 问题链接:AcWing 793. 高精度乘法

    高精度运算_第3张图片

分析

  • 和高精度加法的存储方式一致,假设较大的数已经存储到A中了,较小的数据直接使用int存储即可,假设存储到b中。

  • A的个位开始计算,每次让A[i]乘以b,当前位数据为A[i]*b % 10,进位为A[i]*b / 10

代码

  • C++
#include 
#include 

using namespace std;

vector<int> mul(vector<int> &A, int b) {
     
    
    vector<int> C;
    for (int i = 0, t = 0; i < A.size() || t; i++) {
     
        if (i < A.size()) t += A[i] * b;
        C.push_back(t % 10);
        t /= 10;
    }
    // 去掉前导零
    while (C.size() > 1 && !C.back()) C.pop_back();
    
    return C;
}

int main() {
     
    
    string a;
    int b;
    cin >> a >> b;
    
    vector<int> A;
    for (int i = a.size() - 1; i >= 0; i--) A.push_back(a[i] - '0');
    
    vector<int> C = mul(A, b);
    
    for (int i = C.size() - 1; i >= 0; i--)
        printf("%d", C[i]);
    
    return 0;
}
  • Java
import java.util.*;

public class Main {
     

    // C = A * b
    private static List<Integer> mul(List<Integer> A, int b) {
     

        List<Integer> C = new ArrayList<>();
        int t = 0;  // 进位
        for (int i = 0; i < A.size() || t != 0; i++) {
     
            if (i < A.size()) t += A.get(i) * b;
            C.add(t % 10);
            t /= 10;
        }
        // 去除前导0
        while (C.size() > 1 && C.get(C.size() - 1) == 0) C.remove(C.size() - 1);

        return C;
    }

    public static void main(String[] args) {
     

        // 读入数据
        Scanner scan = new Scanner(System.in);
        char[] a = scan.next().toCharArray();
        int b = scan.nextInt();
        List<Integer> A = new ArrayList<>();
        for (int i = a.length - 1; i >= 0; i--) A.add(a[i] - '0');

        // 算法代码
        List<Integer> C = mul(A, b);

        for (int i = C.size() - 1; i >= 0; i--) System.out.print(C.get(i));
    }
}

扩展:大整数乘以大整数:对应Leetcode 0043 字符串相乘。

AcWing 794. 高精度除法

问题描述

  • 问题链接:AcWing 794. 高精度除法

    高精度运算_第4张图片

分析

  • 和高精度加法的存储方式一致,假设较大的数已经存储到A中了,较小的数据直接使用int存储即可,假设存储到b中。

  • 这里模拟小学的除法进行计算,我们应该从A的最高位开始一位一位的考虑,用r记录余数,初始r=0,每次让r = r*10 + A[i],之后当前为的数据为r/b,余数r变为r%b。可以结合如下例子进行思考:

高精度运算_第5张图片

代码

  • C++
#include 
#include 
#include 

using namespace std;

vector<int> div(vector<int> &A, int b, int &r) {
     
    
    vector<int> C;
    for (int i = A.size() - 1; i >= 0; i--) {
     
        r = r * 10 + A[i];
        C.push_back(r / b);
        r %= b;
    }
    reverse(C.begin(), C.end());  // 低位在索引小的位置,为了和加减乘统一
    // 去掉前导0
    while (C.size() > 1 && !C.back()) C.pop_back();
    
    return C;
}

int main() {
     
    
    string a;
    int b;
    cin >> a >> b;
    
    vector<int> A;
    for (int i = a.size() - 1; i >= 0; i--) A.push_back(a[i] - '0');
    
    int r = 0;
    vector<int> C = div(A, b, r);
    
    for (int i = C.size() - 1; i >= 0; i--)
        printf("%d", C[i]);
    printf("\n%d\n", r);
    
    return 0;
}
  • Java
import java.util.*;

public class Main {
     

    private static int r;  // 余数

    // A / b , 商是C,余数是 r
    private static List<Integer> div(List<Integer> A, int b) {
     

        List<Integer> C = new ArrayList<>();
        for (int i = A.size() - 1; i >= 0; i--) {
     
            r = r * 10 + A.get(i);
            C.add(r / b);
            r %= b;
        }

        Collections.reverse(C);
        // 去掉前导0
        while (C.size() > 1 && C.get(C.size() - 1) == 0) C.remove(C.size() - 1);
        return C;
    }

    public static void main(String[] args) {
     

        // 读入数据
        Scanner scan = new Scanner(System.in);
        String a = scan.next();
        int b = scan.nextInt();
        List<Integer> A = new ArrayList<>();
        for (int i = a.length() - 1; i >= 0; i--) A.add(a.charAt(i) - '0');

        // 算法代码
        List<Integer> C = div(A, b);

        for (int i = C.size() - 1; i >= 0; i--) System.out.print(C.get(i));

        System.out.println();
        System.out.print(r);
    }
}

3. 力扣上的高精度题目

Leetcode 0043 字符串相乘

题目描述:Leetcode 0043 字符串相乘

高精度运算_第6张图片

分析

  • 本题的考点:高精度乘法

  • 首先我们将数据存储到数组A、B中,其中A[0]、 B[0]存储的数字的个位,结果存储到C数组中,分为两步:

    (1)不考虑进位直接将 A [ i ] × B [ j ] A[i] \times B[j] A[i]×B[j]的结果存到 C [ i + j ] C[i + j] C[i+j]中;

    (2)处理C中的进位。如下图: 123 × 456 123 \times 456 123×456

高精度运算_第7张图片

代码

  • C++
class Solution {
     
public:
    string multiply(string num1, string num2) {
     

        vector<int> A, B;
        int n = num1.size(), m = num2.size();
        for (int i = n - 1; i >= 0; i--) A.push_back(num1[i] - '0');
        for (int i = m - 1; i >= 0; i--) B.push_back(num2[i] - '0');

        // (1) 不考虑进位,将结果存入C中
        vector<int> C(n + m);
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++)
                C[i + j] += A[i] * B[j];
        // (2) 考虑进位
        for (int i = 0, t = 0; i < C.size(); i++) {
     
            t += C[i];
            C[i] = t % 10;
            t /= 10;
        }

        // 处理输出
        int k = C.size() - 1;
        while (k && C[k] == 0) k--;
        string res;
        while (k >= 0) res += C[k--] + '0';
        return res;
    }
};
  • Java
class Solution {
     
    public String multiply(String num1, String num2) {
     

        int n = num1.length(), m = num2.length();
        int[] A = new int[n], B = new int[m];
        for (int i = n - 1; i >= 0; i--) A[n - 1 - i] = num1.charAt(i) - '0';
        for (int i = m - 1; i >= 0; i--) B[m - 1 - i] = num2.charAt(i) - '0';
        
        // (1) 不考虑进位,将结果存入C中
        int[] C = new int[n + m];
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++)
                C[i + j] += A[i] * B[j];
        // (2) 考虑进位
        for (int i = 0, t = 0; i < C.length; i++) {
     
            t += C[i];
            C[i] = t % 10;
            t /= 10;
        }

        // 处理输出
        int k = C.length - 1;
        while (k > 0 && C[k] == 0) k--;
        StringBuilder sb = new StringBuilder();
        while (k >= 0) sb.append((char)(C[k--] + '0'));
        return sb.toString();
    }
}
  • Python
class Solution:
    def multiply(self, num1: str, num2: str) -> str:
        n = len(num1); m = len(num2)
        A = []; B = []
        for i in range(n - 1, -1, -1):
            A.append(ord(num1[i]) - ord('0'))
        for i in range(m - 1, -1, -1):
            B.append(ord(num2[i]) - ord('0'))
        C = [0 for _ in range(n + m)]
        for i in range(n):
            for j in range(m):
                C[i + j] += A[i] * B[j]
        t = 0
        for i in range(len(C)):
            t += C[i]
            C[i] = t % 10
            t //= 10

        # 处理输出
        k = len(C) - 1
        while k > 0 and C[k] == 0:
            k -= 1
        res = ""
        while k >= 0:
            res += str(C[k])
            k -= 1
        return res

时空复杂度分析

  • 时间复杂度: O ( n × m ) O(n \times m) O(n×m)nnum1的长度,mnum2的长度。

  • 空间复杂度: O ( n + m ) O(n + m) O(n+m)nnum1的长度,mnum2的长度。

  • 如果数据范围很大,可以考虑使用FFT将时间复杂度优化为 O ( n × l o g ( n ) ) O(n \times log(n)) O(n×log(n))

Leetcode 0066 加一

题目描述:Leetcode 0066 加一

高精度运算_第8张图片

分析

  • 本题的考点:高精度加法

  • 直接使用加法的规则模拟一遍即可,因为加上的是1,因此最终的结果最多比digit多一位,比如99+1=100,因此使用原数组记录结果即可。

  • 注意个位在digits[0]这样比较方便计算,因此需要对输入进行翻转。

代码

  • C++
class Solution {
     
public:
    vector<int> plusOne(vector<int>& digits) {
     

        reverse(digits.begin(), digits.end());
        int t = 1;
        for (auto &x : digits) {
     
            t += x;
            x = t % 10;
            t /= 10;
        }
        if (t) digits.push_back(t);
        reverse(digits.begin(), digits.end());

        return digits;
    }
};
  • Java
class Solution {
     
    public int[] plusOne(int[] digits) {
     

        reverse(digits);
        int t = 1;
        for (int i = 0; i < digits.length; i++) {
     
            t += digits[i];
            digits[i] = t % 10;
            t /= 10;
        }
        if (t != 0) {
     
            int[] res = new int[digits.length + 1];
            System.arraycopy(digits, 0, res, 0, digits.length);
            res[digits.length] = 1;
            reverse(res);
            return res;
        }
        reverse(digits);
        return digits;
    }

    private void reverse(int[] nums) {
     
        for (int i = 0, j = nums.length - 1; i < j; i++, j--) {
     
            int t = nums[i]; nums[i] = nums[j]; nums[j] = t;
        }
    }
}

时空复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n)n为数组长度。

  • 空间复杂度: O ( n ) O(n) O(n)

Leetcode 0067 二进制加和

题目描述:Leetcode 0067 二进制加和

高精度运算_第9张图片

分析

  • 本题的考点:高精度加法

  • 直接使用加法的规则模拟一遍即可。为了处理方便,让个位在数组最低位。

代码

  • C++
class Solution {
     
public:
    string addBinary(string a, string b) {
     

        reverse(a.begin(), a.end());
        reverse(b.begin(), b.end());

        string res;
        for (int i = 0, t = 0; i < a.size() || i < b.size() || t; i++) {
     
            if (i < a.size()) t += a[i] - '0';
            if (i < b.size()) t += b[i] - '0';
            res += to_string(t % 2);
            t /= 2;
        }
        reverse(res.begin(), res.end());
        return res;
    }
};
  • Java
class Solution {
     
    public String addBinary(String a, String b) {
     

        char[] ca = new StringBuilder(a).reverse().toString().toCharArray();
        char[] cb = new StringBuilder(b).reverse().toString().toCharArray();

        StringBuilder sb = new StringBuilder();
        for (int i = 0, t = 0; i < ca.length || i < cb.length || t != 0; i++) {
     
            if (i < ca.length) t += ca[i] - '0';
            if (i < cb.length) t += cb[i] - '0';
            sb.append((char)(t % 2 + '0'));
            t /= 2;
        }
        sb = sb.reverse();
        return sb.toString();
    }
}

时空复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n)n为字符串长度。

  • 空间复杂度:考虑输出 O ( n ) O(n) O(n)

Leetcode 0166 分数到小数

题目描述:Leetcode 0166 分数到小数

高精度运算_第10张图片

分析

  • 本题的考点:模拟、高精度除法

  • 可以分为如下步骤:

    (1)计算结果对应的符号;

    (2)计算整数部分;

    (3)计算小数部分;

  • 关键在于计算小数部分,即如何判断是否是循环小数,以及找出循环节的位置。这里就是模拟手工除法的过程,每次将余数乘10再除以除数,当同一个余数出现两次时,我们就找到了循环节。

高精度运算_第11张图片

  • 我们可以使用哈希表记录每个余数对应的位置,当出现重复的余数时,说明出现了循环节,此时就可以将结果按照题目要求的格式返回。

代码

  • C++
class Solution {
     
public:
    string fractionToDecimal(int numerator, int denominator) {
     

        typedef long long LL;
        LL x = numerator, y = denominator;
        if (x % y == 0) return to_string(x / y);

        string res;
        if ((x < 0) ^ (y < 0)) res += '-';
        x = abs(x), y = abs(y);
        res += to_string(x / y) + '.', x %= y;
        unordered_map<LL, int> hash;  // (余数,余数在字符串中的位置)
        while (x) {
     
            hash[x] = res.size();
            x *= 10;
            res += to_string(x / y), x %= y;
            if (hash.count(x)) {
     
                res = res.substr(0, hash[x]) + '(' + res.substr(hash[x]) + ')';
                break;
            }
        }
        return res;
    }
};
  • Java
class Solution {
     
    public String fractionToDecimal(int numerator, int denominator) {
     

        long x = numerator, y = denominator;
        if (x % y == 0) return String.valueOf(x / y);

        StringBuilder sb = new StringBuilder();
        if ((x < 0) ^ (y < 0)) sb.append("-");
        x = Math.abs(x);
        y = Math.abs(y);
        sb.append(x / y).append(".");
        x %= y;
        HashMap<Long, Integer> hash = new HashMap<>();
        while (x != 0) {
     
            hash.put(x, sb.length());
            x *= 10;
            sb.append(x / y);
            x %= y;
            if (hash.containsKey(x)) {
     
                return sb.substring(0, hash.get(x)) + '(' + sb.substring(hash.get(x)) + ')';
            }
        }
        return sb.toString();
    }
}

时空复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n)n是结果的程度。

  • 空间复杂度: O ( 1 ) O(1) O(1)。哈希表最多存放10个数据,之后必定重复。

Leetcode 0306 累加数

题目描述:Leetcode 0306 累加数

高精度运算_第12张图片

分析

  • 本题的考点:高精度加法

  • 本题枚举前两个数则可以唯一确定后面的数,因此枚举所有的前两个数即可。

  • 因为数据可能会超过int最大值,因此需要用到高精度加法。

代码

  • C++
class Solution {
     
public:
    bool isAdditiveNumber(string num) {
     

        for (int i = 0; i < num.size(); i++)
            for (int j = i + 1; j + 1 < num.size(); j++) {
     
                int a = -1, b = i, c = j;  // 第一个数:num[a+1,b];第二个数:num[b+1,c]
                while (true) {
     
                    if ((b - a > 1 && num[a + 1] == '0') || (c - b > 1 && num[b + 1] == '0')) break;  // 有前导0
                    auto x = num.substr(a + 1, b - a), y = num.substr(b + 1, c - b);
                    auto z = add(x, y);
                    if (num.substr(c + 1, z.size()) != z) break;  // 下一个数不匹配
                    a = b, b = c, c += z.size();
                    if (c + 1 == num.size()) return true;
                }
            }
        return false;
    }

    string add(string x, string y) {
     
        vector<int> A, B, C;
        for (int i = x.size() - 1; i >= 0; i--) A.push_back(x[i] - '0');
        for (int i = y.size() - 1; i >= 0; i--) B.push_back(y[i] - '0');

        for (int i = 0, t = 0; i < A.size() || i < B.size() || t; i++) {
     
            if (i < A.size()) t += A[i];
            if (i < B.size()) t += B[i];
            C.push_back(t % 10);
            t /= 10;
        }
        string z;
        for (int i = C.size() - 1; i >= 0; i--) z += to_string(C[i]);
        return z;
    }
};
  • Java
class Solution {
     
    public boolean isAdditiveNumber(String num) {
     

        char[] nums = num.toCharArray();
        for (int i = 0; i < nums.length; i++) {
     
            for (int j = i + 1; j + 1 < nums.length; j++) {
     
                int a = -1, b = i, c = j;  // 第一个数:num[a+1,b];第二个数:num[b+1,c]
                while (true) {
     
                    if ((b - a > 1 && nums[a + 1] == '0') || (c - b > 1 && nums[b + 1] == '0')) break;  // 有前导0
                    String x = num.substring(a + 1, b + 1), y = num.substring(b + 1, c + 1);
                    String z = add(x, y);
                    if (c + 1 + z.length() > num.length() || !num.substring(c + 1, c + 1 + z.length()).equals(z)) break;
                    a = b;
                    b = c;
                    c += z.length();
                    if (c + 1 == num.length()) return true;
                }
            }
        }
        return false;
    }

    // 高精度加法
    private String add(String x, String y) {
     
        List<Integer> A = new ArrayList<>(), B = new ArrayList<>(), C = new ArrayList<>();
        for (int i = x.length() - 1; i >= 0; i--) A.add(x.charAt(i) - '0');
        for (int i = y.length() - 1; i >= 0; i--) B.add(y.charAt(i) - '0');

        for (int i = 0, t = 0; i < A.size() || i < B.size() || t != 0; i++) {
     
            if (i < A.size()) t += A.get(i);
            if (i < B.size()) t += B.get(i);
            C.add(t % 10);
            t /= 10;
        }
        StringBuilder sb = new StringBuilder();
        for (int i = C.size() - 1; i >= 0; i--) sb.append(C.get(i));
        return sb.toString();
    }
}

时空复杂度分析

  • 时间复杂度: O ( n 3 ) O(n ^ 3) O(n3)n为字符串num长度。

  • 空间复杂度: O ( n ) O(n) O(n)

你可能感兴趣的:(算法,数学,算法)