Leetcode关于加法运算的总结

一个人对行为本身的意愿和他对于行为带来的结果的意愿,两者都是一个人最终是否行动的动机因素。
每一个因素都有自身的拉力,若两个力是相对的,则其中更强大的因素将会决定一个人的行为。

415. 字符串相加
67. 二进制求和

2. 两数相加

445. 两数相加 II

66. 加一

989. 数组形式的整数加法


1. 加法运算

模拟加法运算

真正在刷题的过程中,我们只需要记住几点即可:

  1. 低位到高位,逐位求和的算法为:sum = x + y + carry.( x和y 分别来表示每位的数值,carry 表示进位,默认为0)
  2. 当前位的值:cur = sum % 10
  3. 进位carry的值:carry = sum / 10;

PS:因为是从低位 ->高位,所以需要注意结果是否需要翻转,通常可借助于:

  • 反转操作:

    1. StringBuilder/ StringBuffer 的 reverse();
    2. Collections.reverse();

  • 头插法思想:

    1. LinkedList的addFirst(value) ;
    2. 链表的头插法;
    3. ArrayList的add(0, value)

下面我们通过这个模拟操作,来解决Leetcode的相关问题。


415. 字符串相加

给定两个字符串形式的非负整数 num1 和num2 ,计算它们的和并同样以字符串形式返回。

你不能使用任何內建的用于处理大整数的库(比如 BigInteger), 也不能直接将输入的字符串转换为整数形式。

1. 常规写法
 	 public String addStrings(String num1, String num2) {
    
    
        StringBuilder sb = new StringBuilder();
        
        int i = num1.length() -1;
        int j = num2.length() -1;
        
        int carry = 0;

        while(i >= 0 || j >= 0 || carry > 0){
    
    
            // 字符0就是48
            int x = (i >= 0) ? num1.charAt(i--) - '0' : 0;
            int y = (j >= 0) ? num2.charAt(j--) - '0' : 0;
            
            int sum = (x + y + carry);
            int curVal = sum % 10; //当前位的值
 			sb.append(curVal);
 			
            carry = sum / 10;// 处理进位的值
        }

        return sb.reverse().toString();
    }

2. 精炼写法

本质上没有任何区别,只是在熟练之后,我们往往会在不破坏代码可读性的情况,对代码做出优化。

 public String addStrings(String num1, String num2) {
    
    
        StringBuilder sb = new StringBuilder();

        int i = num1.length() -1;
        int j = num2.length() -1;
        
        int carry = 0;

        while(i >= 0 || j >= 0 || carry > 0){
    
    
            // 字符0就是48
            carry += (i >= 0) ? num1.charAt(i--) - '0' : 0;
            carry += (j >= 0) ? num2.charAt(j--) - '0' : 0;
            
            sb.append(carry % 10);
            
            carry /= 10;// 处理进位的值
        }

        return sb.reverse().toString();
    }

趁热打铁-67. 二进制求和


2. 链表中的两数相加

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。

你可以假设除了数字 0 之外,这两个数都不会以 0 开头。

在这里插入图片描述

In a word, 求数据结构之链表的两数之和问题

public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
    
    
        int carry = 0;
        ListNode dummy = new ListNode(-1);
        ListNode cur = dummy;

        while(l1 != null || l2 != null || carry != 0){
    
    
            carry += (l1 != null) ? l1.val : 0;
            carry += (l2 != null) ? l2.val : 0;

            cur.next = new ListNode(carry % 10);
            cur = cur.next;

            carry /= 10;

            if(l1 != null){
    
    
                l1 = l1.next;
            }
            if(l2 != null){
    
    
                l2 = l2.next;
            }
        }
        return dummy.next;
    }

445. 链表中的两数相加 II

闲暇之余,可以顺手解决 剑指 Offer II 025. 链表中的两数相加

给你两个 非空 链表来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储一位数字。将这两数相加会返回一个新的链表。
你可以假设除了数字 0 之外,这两个数字都不会以零开头。

在这里插入图片描述
进阶:如果输入链表不能翻转该如何解决?

人生苦短,我要翻转 , 感兴趣的可以点进去看一下。

进阶解法

不让我们翻转,那我们就采用前面介绍的一些手段来达到翻转的效果。
需要注意的是,此题有两处需要翻转:

  1. 操作数的链表翻转 ;
  2. 结果需要翻转;

最佳方案; 数据结构(栈) + 链表的头插法

 	public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
	// 第一步:入栈操作
	    Stack<Integer> s1 = new Stack<>();
        Stack<Integer> s2 = new Stack<>();

        while(l1 != null){
            s1.push(l1.val);
            l1 = l1.next;
        }

        while(l2 != null){
            s2.push(l2.val);
            l2 = l2.next;
        }
        // 头插法
 		ListNode head = null;
        int carry = 0;

        while(!s1.isEmpty() || !s2.isEmpty() || carry > 0){
            carry += (s1.isEmpty()) ? 0 : s1.pop();
            carry += (s2.isEmpty()) ? 0 : s2.pop();

            ListNode node =  new ListNode(carry % 10);
            node.next = head;
            head = node;
            carry /= 10;
        }

        return head;
  }

43. 字符串相乘

在这里插入图片描述

 public String multiply(String num1, String num2) {
    
    
        if(num1.equals("0") || num2.equals("0")){
    
    
            return "0";
        }

        if(num1.equals("1")){
    
    
            return num2;
        }

        if(num2.equals("1")){
    
    
            return num1;
        }

        String result = "0";

        int len1 = num1.length();
        int len2 = num2.length();
        
        for(int i = len2 - 1; i >= 0;i--){
    
    
            int carry = 0;
            StringBuilder tmp = new StringBuilder();
            //补0
            for(int j = 0;j < len2-1 - i;j++){
    
    
                tmp.append(0);
            }
            int n2 = num2.charAt(i) - '0';

            for(int j = len1 - 1; j >= 0|| carry != 0; j--){
    
    
                int n1 = j < 0 ? 0:num1.charAt(j) - '0';
                int product = (n1 * n2 +carry) % 10;
                tmp.append(product);
                carry = (n1 * n2+carry)/ 10;
            }

            result = addStrings(result,tmp.reverse().toString());
        }
        return result;
    }
	// 实现字符串相加的功能
    public String addStrings(String num1,String num2){
    
    
        StringBuilder sb = new StringBuilder();
        int carry = 0;

        int i1 = num1.length() - 1;
        int i2 = num2.length() - 1;

        while(i1 >= 0 || i2 >= 0 || carry > 0){
    
    
            carry += i1 >= 0 ? (num1.charAt(i1--) - '0'):0;
            carry += i2 >= 0 ? (num2.charAt(i2--) - '0'):0;
            sb.append(carry % 10);
            carry /= 10;
        }
        return sb.reverse().toString();
    }


```


猜你喜欢

转载自blog.csdn.net/wangcheeng/article/details/124595076