NC 001 大数加法

Avatar photo

题目:
以字符串的形式读入两个数字,编写一个函数计算它们的和,以字符串形式返回。
数据范围:,字符串仅由’0’~‘9’构成
要求:时间复杂度 

首先先想到的还是通过从右向左遍历一位一位相加,像是小学生手算一样计算进位最后得到结果:

import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 计算两个数之和
     * @param s string字符串 表示第一个整数
     * @param t string字符串 表示第二个整数
     * @return string字符串
     */
    public String solve (String s, String t) {
        // write code here
        //溢出标记
        int over = 0;
        String result = "";
        int index = 1;
        int loopleft = Math.max(s.length(), t.length());
        int[] s_array = s.chars().toArray();
        int[] t_array = t.chars().toArray();
        for(; loopleft > 0; loopleft--,index ++){
            int a = s.length() >= index ? (s_array[s.length() - index] - '0'):0;
            int b = t.length() >= index ? (t_array[t.length() - index] - '0'):0;
            result = ((a+b+over)>0 ? (a+b+over) % 10 : 0) + result;
            over = (a+b+over)>0 ? (a+b+over) / 10 : 0; 
        }
        result = (over==0 ? "" : "1") + result; 
        
        return result;
    }
}

超了近一倍的时间,显然不行,那么就要减少运算次数,我先想到的是转换函数paresInt和charAt,虽然是java内部实现的,但是因为是通用方法,会有很多冗余判断,比如下标长度之类的,因此我选择用switch直接比较来映射结果:

import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 计算两个数之和
     * @param s string字符串 表示第一个整数
     * @param t string字符串 表示第二个整数
     * @return string字符串
     */
    public String solve (String s, String t) {
        // write code here
        //溢出标记
        int over = 0;
        long start = System.currentTimeMillis();
        int SPLIT_LENGTH = 16;
        String result = "", format = "";
        for(int i = 0; i< SPLIT_LENGTH; i++){
            format += "0";
        }
        long a,b;
        int times = Math.max((s.length()-1)/SPLIT_LENGTH, (t.length()-1)/SPLIT_LENGTH);
        int index = 0, sl = s.length(), tl = t.length();
        boolean sOut = false, tOut = false;
        int s_start, s_end, t_start, t_end;
        for(;times >= 0; times--,index++){
            if(sOut){
                a = 0l;
            }else if((index+1)*SPLIT_LENGTH >= sl-1){
                System.out.println("s is out");
                s_start = 0;
                if(index == 0){
                    s_end = sl;
                }else{
                    s_end = sl - index * SPLIT_LENGTH;
                }
                sOut = true;
                a = Long.parseLong(s.substring(s_start, s_end));
            }else{
                s_start = sl - (index+1)*SPLIT_LENGTH;
                s_end = sl - index * SPLIT_LENGTH;
                a = Long.parseLong(s.substring(s_start, s_end));
            }
           
            if(tOut){
                b = 0l;
            }else if((index+1)*SPLIT_LENGTH >= tl-1){
                System.out.println("t is out");
                t_start = 0;
                if(index == 0){
                    t_end = tl;
                }else{
                    t_end = tl - index * SPLIT_LENGTH;
                }
                tOut = true;
                b = Long.parseLong(t.substring(t_start, t_end));
            }else{
                t_start = tl - (index+1)*SPLIT_LENGTH;
                t_end = tl - index * SPLIT_LENGTH;
                b = Long.parseLong(t.substring(t_start, t_end));
            }

            System.out.println("a:" + a + " b:" + b + " over:" + over);
            Long tmp = a + b + over;
            
            if( sOut && tOut){
                result = tmp + result;
            }else{
                if(tmp.toString().length() > SPLIT_LENGTH) over = 1; else over = 0;
                result = (format + tmp).substring((""+tmp).length()) + result;
            }
        }
        return result;
    }
}

这次修改通过long形计算来提高算速,用一个SPLIT_LENGTH来控制分组大小,最终达到358ms通过了测试。

但是查看排名发现,最快的只需要53ms,使用的还是第一种思路,于是尝试优化第一种。

import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 计算两个数之和
     * @param s string字符串 表示第一个整数
     * @param t string字符串 表示第二个整数
     * @return string字符串
     */
    public String solve (String s, String t) {
        // write code here
        //溢出标记
        int over = 0;
        int index = 1, sl=s.length(), tl=t.length();
        char[] result = new char[Math.max(sl, tl)];
        for(int loopleft = Math.max(sl, tl); loopleft >= index; index++){
            if(sl >= index) over += s.charAt(sl - index)-'0';
            if(tl >= index) over += t.charAt(tl - index)-'0';
            result[loopleft - index] = (char)('0' + over % 10);
            over = over / 10;
        }
        return (over==0?"":"1") + new String(result);
    }
}

最终51ms。