目录
1、Leetcode 67:二进制求和
2、Leetcode 66:加一
3、Leetcode 989:数组形式的整数加法
4、Leetcode 2:两数相加
5、Leetcode 445:两数相加Ⅱ
6、Leetcode 43:字符串相乘
7、总结
这几天刷题,碰到好几次关于加法的题目。这些题目包括:二进制求和、两数相加、链表相加、字符串相乘、数组形式的整数加法。所以今天就特意写一个关于加法的博客,做个小总结。
链接: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();
}
}
链接: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代表下一轮进入循环的进位值。举个例子:
代码:
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;
}
}
链接: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;
}
}
链接:Leecode 2:两数相加
题目描述:
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例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;
}
}
链接:Leetcode 445:两数相加Ⅱ
题目描述:
给你两个 非空 链表来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储一位数字。将这两数相加会返回一个新的链表。
你可以假设除了数字 0 之外,这两个数字都不会以零开头。
示例1:
输入: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;
}
}
链接:Leetcode 43:字符串相乘
题目描述:
给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。
注意:不能使用任何内置的 BigInteger 库或直接将输入转换为整数。
示例 1:
输入: num1 = "2", num2 = "3"
输出: "6"
示例 2:
输入: num1 = "123", num2 = "456"
输出: "56088"
思路:
「竖式乘法」:
代码:
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();
}
}
以上都是Leetcode中的加法题目,可以看出其主要的处理在于进制位的使用: