玩转Leetcode里的加法题目

目录

1、Leetcode 67:二进制求和

2、Leetcode 66:加一

3、Leetcode 989:数组形式的整数加法

4、Leetcode 2:两数相加

 5、Leetcode 445:两数相加Ⅱ

6、Leetcode 43:字符串相乘

7、总结


 这几天刷题,碰到好几次关于加法的题目。这些题目包括:二进制求和、两数相加、链表相加、字符串相乘、数组形式的整数加法。所以今天就特意写一个关于加法的博客,做个小总结。

1、Leetcode 67:二进制求和

链接:Leetcode 67:二进制求和

题目描述:

给你两个二进制字符串,返回它们的和(用二进制表示)。

输入为 非空 字符串且只包含数字 1 和 0。

示例 1:

输入: a = "11", b = "1"

输出: "100"

示例 2:

输入: a = "1010", b = "1011"

输出: "10101"

思路:

        利用双指针向后遍历,然后将给定的两个字符串的对应位置进行相加,并记录进位值和余数值。需要注意的是:当两个字符串遍历结束后,需要对进制位进行判断,如果进位值不为0,则应该加入结果。

代码:

class Solution {
    public String addBinary(String a, String b) {
        //记录结果
       StringBuffer sb = new StringBuffer();
       //将字符串转为字符数组
        char[] ch1 = a.toCharArray();
        char[] ch2 = b.toCharArray();
        //获取长度
        int cur1 = ch1.length-1, cur2 = ch2.length-1;
        //val代表进位的值
        int val = 0;
        while(cur1 >= 0 || cur2 >= 0){
            int temp  = val;
            //相加
            temp += cur1 >= 0 ? ch1[cur1--]-'0' : 0;
            temp += cur2 >= 0 ? ch2[cur2--]-'0' : 0;
            //前插结果
            sb.insert(0, temp%2);
            val = temp/2;
        }
        //当两个字符串相加完毕之后,如果进位值不为0,则应该加入sb的结果集中
        if(val == 1){
            sb.insert(0, 1);
        }
        return sb.toString();
    }
}

2、Leetcode 66:加一

链接:Leetcode 66:加一

题目描述:

给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。

最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。

你可以假设除了整数 0 之外,这个整数不会以零开头。

示例 1:

输入:digits = [1,2,3]

输出:[1,2,4]

解释:输入数组表示数字 123。

示例 2:

输入:digits = [4,3,2,1]

输出:[4,3,2,2]

解释:输入数组表示数字 4321。

示例 3:

输入:digits = [0]

输出:[1]

思路:

        题目指出需要进行加一操作,因此从后向前进行遍历,然后更新数组元素值即可。这里定义了一个val,它有两个含义:在未进入循环之前,val等于1,代表进行加一操作;在进入循环之后,val代表下一轮进入循环的进位值。举个例子:

  • 如果digits[]的元素值为:[1,2,3],那么完成加一操作之后,则结果为[1,2,4]
  • 如果digits[]的元素值为:[1,2,9],那么完成加一操作之后,则结果为[1,3,0],当9+1之后,进入下一轮的进制位val=(9+1)/10

代码:

class Solution {
    public int[] plusOne(int[] digits) {
        //初始情况下val等于1,是因为我们要从后向前进行遍历。在循环过程中,val就代表下一轮要使用到的进制位
        int val = 1;
        //从后向前遍历
        for(int i=digits.length-1; i>=0; i--){
            int data = digits[i] + val;
            digits[i]  = data%10;
            val = data / 10;
        }
        //遍历结束后,如果val等于1,则仍需加入结果
        if(val == 1){
            int[] result = new int[digits.length+1];
            result[0] = 1;
            return result;
        }
        return digits;
    }
}

3、Leetcode 989:数组形式的整数加法

链接:Leetcode 989:数组形式的整数加法

题目描述:

整数的 数组形式  num 是按照从左到右的顺序表示其数字的数组。

例如,对于 num = 1321 ,数组形式是 [1,3,2,1] 。
给定 num ,整数的 数组形式 ,和整数 k ,返回 整数 num + k 的 数组形式 。

示例 1:

输入:num = [1,2,0,0], k = 34

输出:[1,2,3,4]

解释:1200 + 34 = 1234

示例 2:

输入:num = [2,7,4], k = 181

输出:[4,5,5]

解释:274 + 181 = 455

示例 3:

输入:num = [2,1,5], k = 806

输出:[1,0,2,1]

解释:215 + 806 = 1021

思路:

        本题给定了一个数字数组num和数字k,最终要返回的结果是List类型。因此,先将数字k转为了list,然后从后向前进行遍历并进行相加。最后同样是需要判断进制位的。

代码:

class Solution {
    public List addToArrayForm(int[] num, int k) {
        //将数字k转为list
        List list = getNumArray(k);
        //记录结果集
        List result = new ArrayList<>();
        int i = num.length-1, j = list.size()-1;
        //进制位
        int val = 0;
        //从后向前进行遍历
        while(i >= 0 || j >= 0){
            int temp = val;
            //对应位相加
            if(i >= 0){
                temp += num[i--];
            }
            if(j >= 0){
                temp += list.get(j--);;
            }
            //添加结果集
            result.add(0, temp%10);
            val = temp/10;
        }
        //遍历结束后,进制位如果不为0,同样需要加入list
        if(val == 1){
            result.add(0, 1);
        }    
        return result;
    }
    //将数字转为list
    public List getNumArray(int data){
        List list = new ArrayList<>();
        while(data > 0){
            list.add(0, data%10);
            data /= 10;
        }
        return list;
    }
}

4、Leetcode 2:两数相加

链接:Leecode 2:两数相加

 题目描述:

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。

请你将两个数相加,并以相同形式返回一个表示和的链表。

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

示例1:

玩转Leetcode里的加法题目_第1张图片

输入:l1 = [2,4,3], l2 = [5,6,4]

输出:[7,0,8]

解释:342 + 465 = 807.

示例 2:

输入:l1 = [0], l2 = [0]

输出:[0]

示例 3:

输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]

输出:[8,9,9,9,0,0,0,1]

思路:

本题和前面题的区别有两个部分:

  • 给定的参数是链表
  • 前面的题我们都需要从后向前进行遍历,而给定的链表不需要从后向前遍历,而是直接迭代即可。

本题思路和前面题的思路一致。

代码:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        //两个指针指向两个链表
        ListNode cur1 = l1, cur2 = l2;
        //存储结果
        ListNode newHead = new ListNode();
        ListNode temp = newHead;
        //进制位
        int val = 0;
        //进行遍历
        while(l1 != null || l2 != null){
            //相加
            if(l1 != null){
                val += l1.val;
                l1 = l1.next;
            }
            if(l2 != null){
                val += l2.val;
                l2 = l2.next;
            }
            //添加到结果链表中
            ListNode node = new ListNode(val%10);
            temp.next = node;
            temp = temp.next;
            val /= 10;
        }
        //处理进制位
        if(val == 1){
            ListNode node = new ListNode(1);
            temp.next = node;
            temp = temp.next;
        }
        return newHead.next;
    }
}

 5、Leetcode 445:两数相加Ⅱ

链接:Leetcode 445:两数相加Ⅱ

题目描述:

给你两个 非空 链表来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储一位数字。将这两数相加会返回一个新的链表。

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

示例1:

玩转Leetcode里的加法题目_第2张图片

输入:l1 = [7,2,4,3], l2 = [5,6,4]

输出:[7,8,0,7]

示例2:

输入:l1 = [2,4,3], l2 = [5,6,4]

输出:[8,0,7]

示例3:

输入:l1 = [0], l2 = [0]

输出:[0]

思路:

本题和上一题的区别在于:需要从后向前遍历,所以就需要进行反转链表的操作

代码:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        //反转链表
        l1 = reverseList(l1);
        l2 = reverseList(l2);
        ListNode newHead = new ListNode();
        ListNode temp = newHead;
        int val = 0;
        while(l1 != null || l2 != null){
            if(l1 != null){
                val += l1.val;
                l1 = l1.next;
            }
            if(l2 != null){
                val += l2.val;
                l2 = l2.next;
            }
            ListNode node = new ListNode(val%10);
            temp.next = node;
            temp = temp.next;
            val /= 10;
        }
        if(val == 1){
            ListNode node = new ListNode(1);
            temp.next = node;
            temp = temp.next;
        }
        ListNode result = reverseList(newHead.next);
        return result;
    }
    //反转链表
    public ListNode reverseList(ListNode head){
        ListNode cur = head, pre = null;
        while(cur != null){
            ListNode temp = cur.next;
            cur.next = pre;
            pre = cur;
            cur = temp;
        }
        return pre;
    }
}

6、Leetcode 43:字符串相乘

链接:Leetcode 43:字符串相乘

题目描述:

给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。

注意:不能使用任何内置的 BigInteger 库或直接将输入转换为整数。

示例 1:

输入: num1 = "2", num2 = "3"

输出: "6"

示例 2:

输入: num1 = "123", num2 = "456"

输出: "56088"

思路:

  • 如果num1和 num2 之一是 0,则直接将 0 作为结果返回即可
  • 如果num1 和num2都不是 0,则可以通过模拟「竖式乘法」的方法计算乘积。从右往左遍历乘数,将乘数的每一位与被乘数相乘得到对应的结果,再将每次得到的结果累加。这道题中,被乘数num1,乘数是num2 。
  • 需要注意的是,num2除了最低位以外,其余的每一位的运算结果都需要补 0

「竖式乘法」:

玩转Leetcode里的加法题目_第3张图片

 代码:

class Solution {
    public String multiply(String num1, String num2) {
        //处理特殊情况,如果其中一个为0,则直接结果返回0
        if (num1.equals("0") || num2.equals("0")) {
            return "0";
        }
        String ans = "0";
        //长度
        int m = num1.length(), n = num2.length();
        for (int i = n - 1; i >= 0; i--) {
            StringBuffer curr = new StringBuffer();
            int add = 0;
            for (int j = n - 1; j > i; j--) {
                curr.append(0);
            }
            int y = num2.charAt(i) - '0';
            //将num1的每一位都和num2进行乘法运算
            for (int j = m - 1; j >= 0; j--) {
                int x = num1.charAt(j) - '0';
                int product = x * y + add;
                curr.append(product % 10);
                add = product / 10;
            }
            //如果进位不为0,则append
            if (add != 0) {
                curr.append(add % 10);
            }
            //进行结果累加
            ans = addStrings(ans, curr.reverse().toString());
        }
        return ans;
    }
    //两个字符串相加
    public String addStrings(String num1, String num2) {
        int i = num1.length() - 1, j = num2.length() - 1, add = 0;
        StringBuffer ans = new StringBuffer();
        while (i >= 0 || j >= 0 || add != 0) {
            //获取当前位置的数字
            int x = i >= 0 ? num1.charAt(i) - '0' : 0;
            int y = j >= 0 ? num2.charAt(j) - '0' : 0;
            //add代表进位制
            int result = x + y + add;
            ans.append(result % 10);
            add = result / 10;
            i--;
            j--;
        }
        ans.reverse();
        return ans.toString();
    }
}

7、总结

        以上都是Leetcode中的加法题目,可以看出其主要的处理在于进制位的使用:

  • 通过对元素相应位置求和后,分别进行 / 操作和 % 操作。
  • 在整个迭代循环结果后,需要判断进制位的值。

你可能感兴趣的:(LeetCode,java,leetcode,后端,算法,数据结构)