目录
1.字符串相加
1.对应letecode链接:
2.题目描述:
给定两个字符串形式的非负整数 num1 和num2 ,计算它们的和并同样以字符串形式返回。
你不能使用任何內建的用于处理大整数的库(比如 BigInteger), 也不能直接将输入的字符串转换为整数形式。
示例 1:
输入:num1 = "11", num2 = "123"
输出:"134"
示例 2:输入:num1 = "456", num2 = "77"
输出:"533"
示例 3:输入:num1 = "0", num2 = "0"
输出:"0"提示:
1 <= num1.length, num2.length <= 104
num1 和num2 都只包含数字 0-9
num1 和num2 都不包含任何前导零
3.💖思考方式:⭐⭐⭐⭐
加法模板:while(表达式1||表达式2||carry!=0){};其中carry代表进位
这也就是我们小学学过的加法列式计算:
1.两个「加数」的右端对齐;
2.从最右侧开始,从右向左依次计算对应的两位数字的和,如果有进位需要加上进位。如果3.和大于等于 10,则把和的个位数字计入结果,并向前面进位;
重复步骤 2;
4.当两个「加数」的每个位置都计算完成,如果最后仍有进位,需要把进位数字保留到计算结果中总结一下大概就是:
- 「求加法」系列题目都不难,其实就是 列式计算。
- 需要注意的是:
- while循环结束条件;
- 遍历两个「加数」不要越界;
- 进位。
- 最后的结果需要翻转
代码说明:
while (表达式1 ||表达式2 || carry != 0)含义:
字符串 num1 和 num2 只要有一个没遍历完,那么就继续遍历;
如果字符串 num1 和 num2 都遍历完了,但是最后留下的进位 carry != 0,那么需要把进位也保留到结果中。
对应代码:
class Solution { public: string addStrings(string num1, string num2) { string s; int len1=num1.size()-1; int len2=num2.size()-1; int carry=0; while(len1>=0||len2>=0||carry) { int sum=0; if(len1>=0) { sum+=num1[len1]-'0'; } if(len2>=0) { sum+=num2[len2]-'0'; } sum+=carry; s+=to_string(sum%10); carry=sum/10; len1--; len2--; } //翻转 reverse(s.begin(),s.end()); return s; } };
加一:
对应letecode链接:
题目描述:
给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。
最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。
你可以假设除了整数 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]提示:
1 <= digits.length <= 100
0 <= digits[i] <= 9
解题思路:和上面那题完全相同,只不过上题是两个字符串相加,这里是一个数组和一个数字相加而已只要稍微改动一下即可
对应代码:⭐⭐⭐⭐
class Solution { public: vector<int> plusOne(vector<int>& digits) { vector<int>tmp; int carry=0; int k=1; int len=digits.size()-1; while(len>=0||carry)//进位不等于0继续计算将其加到结果里面去 { int sum=0; if(len>=0) { sum+=digits[len]; } if(k>0) { sum+=k; } sum+=carry; tmp.push_back(sum%10); carry=sum/10; len--; k--; } reverse(tmp.begin(),tmp.end()); return tmp; } };
数组形式的加法:
对应letecode链接:
对应letcode题目:
对于非负整数 X 而言,X 的数组形式是每位数字按从左到右的顺序形成的数组。例如,如果 X = 1231,那么其数组形式为 [1,2,3,1]。
给定非负整数 X 的数组形式 A,返回整数 X+K 的数组形式。
示例 1:
输入:A = [1,2,0,0], K = 34
输出:[1,2,3,4]
解释:1200 + 34 = 1234
示例 2:输入:A = [2,7,4], K = 181
输出:[4,5,5]
解释:274 + 181 = 455
示例 3:输入:A = [2,1,5], K = 806
输出:[1,0,2,1]
解释:215 + 806 = 1021
示例 4:输入:A = [9,9,9,9,9,9,9,9,9,9], K = 1
输出:[1,0,0,0,0,0,0,0,0,0,0]
解释:9999999999 + 1 = 10000000000
提示:
1 <= A.length <= 10000
0 <= A[i] <= 9
0 <= K <= 10000
如果 A.length > 1,那么 A[0] != 0
解题思路和第一题基本一样:
对应代码:
class Solution { public: vector<int> addToArrayForm(vector<int>& num, int k) { vector<int>ans; int len=num.size()-1; int carry=0; while(len>=0||carry||k){//注意有可能k的位数要比num的长度要长此时k,有存在数组已经走完,而进位也是0但k却不是0; int sum=0; if(len>=0){ sum+=num[len]; } if(k){ sum+=k%10; } sum+=carry; ans.push_back(sum%10); carry=sum/10;//保存进位 k/=10; len--; } reverse(ans.begin(),ans.end()); return ans; } };
二进制求和:
对应letecode链接:
题目描述:
给你两个二进制字符串,返回它们的和(用二进制表示)。
输入为 非空 字符串且只包含数字 1 和 0。
示例 1:
输入: a = "11", b = "1"
输出: "100"
示例 2:输入: a = "1010", b = "1011"
输出: "10101"提示:
每个字符串仅由字符 '0' 或 '1' 组成。
1 <= a.length, b.length <= 10^4
字符串如果不是 "0" ,就都不含前导零。
这题就是上面第二题换了一个说法:
对应代码:
class Solution { public: string addBinary(string a, string b) { string s; int carry=0; int lena=a.size()-1; int lenb=b.size()-1; while(lena>=0||lenb>=0||carry) { int sum=0; if(lena>=0) { sum+=a[lena]-'0'; } if(lenb>=0) { sum+=b[lenb]-'0'; } sum+=carry; s+=to_string(sum%2); carry=sum/2; lena--; lenb--; } reverse(s.begin(),s.end()); return s; } };
下面来看几个链表的题:
对应letecode 链接:
题目描述:
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 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]提示:
每个链表中的节点数在范围 [1, 100] 内
0 <= Node.val <= 9
题目数据保证列表表示的数字不含前导零
3.💖思考方式:⭐⭐⭐⭐:
a 两条链表相加,返回的结果要求是链表,每次插值的时候都要在链表的尾端添加。
需要一个返回结果的链表ans,需要一个指针,每次添加后都指向最后一个节点。
b. 如果有进数(两数想和大于十进1),下次相加时一起加上。
c. 两条链表长度可能不相等,因此结束循环后,需要判断是否有未遍历完的链表,有则单独遍历,没有则进入下一步。
d. 当两条链表都遍历结束,还需要判断进数是否为0,为0什么也不做,不为0在运行结果的链表尾部添加值为1的节点。
c. 最后可以直接返回ans链表思路和之前类似
对应代码:
class Solution { public: ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) { ListNode*ans=new ListNode(-1); ListNode*tmp=ans; int carry=0; while(l1||l2||carry){ int nextsum=0; if(l1){ nextsum+=l1->val; l1=l1->next; } if(l2){ nextsum+=l2->val; l2=l2->next; } nextsum+=carry; tmp->next=new ListNode(nextsum%10); tmp=tmp->next; carry=nextsum/10; } return ans->next; } };
两数之和II
1.对应letecode链接:
2.题目描述:
给你两个 非空 链表来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储一位数字。将这两数相加会返回一个新的链表。
你可以假设除了数字 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]提示:
链表的长度范围为 [1, 100]
0 <= node.val <= 9
输入数据保证链表代表的数字无前导 0进阶:如果输入链表不能修改该如何处理?换句话说,不能对列表中的节点进行翻转。
3.💖思考方式:⭐⭐⭐⭐:
这道题可以通过使用栈来解决,我们需要构建两个栈,将两个链表中的值分别压入这两个栈中。
每次都从两个栈中各弹出一个元素,就是我们所需要的最末位元素,按照计算方式,相加取模求当前位的值,同时我们还需要记录当前位的进位。最后,我们使用获得的值,构建一个节点。
我们需要使用一个指针作为头指针,指向当前节点。每次新增节点,我们只需要将新节点插入到头指针之后即可。
对应代码:
class Solution { public: ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) { stack<ListNode*>stk1; stack<ListNode*>stk2; while(l1){//将链表放到栈里面 stk1.push(l1); l1=l1->next; } while(l2){ stk2.push(l2); l2=l2->next; } int carry=0;//进位 ListNode*ans=nullptr;//新链表的头 while(!stk2.empty()||!stk1.empty()||carry){ int sum=0; if(!stk1.empty()){//栈不为空才取数据 sum+=stk1.top()->val; stk1.pop(); } if(!stk2.empty()){ sum+=stk2.top()->val; stk2.pop(); } sum+=carry; ListNode*tmp=new ListNode(sum%10); tmp->next=ans;//头插 ans=tmp; carry=sum/10;//进位 } return ans; } };
方法二:
我们可以利用之前用的链表相加的方法:但是使用之前我们要把两个链表翻转一个使用之前的方法在翻转一遍就是我们要的答案:⭐⭐⭐⭐:
对应代码:
class Solution { public: ListNode*Reverse(ListNode*head){ ListNode*prev=nullptr; ListNode*cur=head; while(cur){ ListNode*next=cur->next; cur->next=prev; prev=cur; cur=next; } return prev; } ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) { l1= Reverse(l1); l2=Reverse(l2); int carry=0; ListNode*dummyHead=new ListNode(-1); ListNode*ans=dummyHead; while(l1||l2||carry){ int sum=0; if(l1){链表不为空才加 sum+=l1->val; l1=l1->next; } if(l2){ sum+=l2->val; l2=l2->next; } sum+=carry; ans->next=new ListNode(sum%10);//链接 ans=ans->next; carry=sum/10;//保存进位 } dummyHead->next=Reverse(dummyHead->next);//翻转 return dummyHead->next; } };
加法模板:学会这个后你将轻松搞定这一类题
总结一下大概就是:
- 「求加法」系列题目都不难,其实就是 列式计算。
- 需要注意的是:
- while循环结束条件;
- 遍历两个「加数」不要越界;
- 进位。
- 最后的结果需要翻转
最后:
🙌🙌🙌🙌
结语:对于个人来讲,在leetcode上进行探索以及单人闯关是一件有趣的时间,一个程序员,如果不喜欢编程,那么可能就失去了这份职业的乐趣。刷到我的文章的人,我希望你们可以驻足一小会,忙里偷闲的阅读一下我的文章,可能文章的内容对你来说很简单,(^▽^)不过文章中的每一个字都是我认真专注的见证!希望您看完之后,若是能帮到您,劳烦请您简单动动手指鼓励我,我必回报更大的付出~