【LeetCode】2.两数相加
生活随笔
收集整理的這篇文章主要介紹了
【LeetCode】2.两数相加
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1.兩數相加
一、問題描述
給你兩個?非空 的鏈表,表示兩個非負的整數。它們每位數字都是按照?逆序?的方式存儲的,并且每個節點只能存儲?一位?數字。
請你將兩個數相加,并以相同形式返回一個表示和的鏈表。
你可以假設除了數字 0 之外,這兩個數都不會以 0?開頭。
二、問題簡化
這個問題實際上是為了解決大數計算問題,即比較大的數字的計算(眾所周知int型的表示范圍有限)。
很明顯題目說的是十進制,實際其他進制也是一樣的。
十進制一位只有10個值,用4位2進制就足夠表示了,也就是32位可以表示8個十進制。不過int型的計算是快于其他類型的(由于硬件的架構),所以先不考慮這么多,使用int型的鏈表表示大數類即可:
typedef list<int> BigInteger;在定義大數類之后,求和函數傳入兩個值,返回一個值,如下::
BigInteger addTwoNumber(const BigInteger& a, const BigInteger& b)?三、功能實現
基本算法
1.首先區分出長鏈和短鏈,也就是哪個數字更短。
2.遍歷短鏈,同時遍歷長鏈,之間相加的結果插入到結果鏈,并記錄是否進位(很明顯,進位只能進1)。
3.將長鏈剩余部分添加到結果鏈,同時也可能發生進位。
4.最后還可能進位,最后單獨判斷一次
BigInteger addTwoNumber(const BigInteger& a, const BigInteger& b) {BigInteger ret;const BigInteger* bi_s;const BigInteger* bi_l;//區分長短鏈if (a.size() > b.size()){bi_l = &a;bi_s = &b;}else{bi_l = &b;bi_s = &a;}//取較小長度int length = bi_s->size();//0為短鏈auto iter0 = bi_s->begin();auto iter1 = bi_l->begin();//是否進位標記bool carry = false;//遍歷完短鏈for (int i = 0; i != length; ++i){//求和int sum = *iter0 + *iter1;//如果上次遍歷結果進位,則加1if (carry) ++sum;if (sum < 10)carry = false;//否則不進位else{//如果結果大于等于10,則進位(標記進位,下次循環使用)sum %= 10;carry = true;}ret.push_back(sum);++iter0;++iter1;}//再添加較長數字的剩余高位(考慮進位)for (; iter1 != bi_l->end(); ++iter1){if (carry){//進位則加1,同時還可能發生繼續進位int num = *iter1 + 1;if (num < 10)carry = false;elsenum %= 10;ret.push_back(num);}else{ret.push_back(*iter1);carry = false;}}//最后進位可能if (carry){ret.push_back(1);}return ret; }?打印功能
需要直觀的觀察數字,所以我們用逆序迭代器打印每一個節點,以及直接打印出a加b的結果:
void PrintNumber(const BigInteger& bi) {//逆序打印for (auto iter = bi.rbegin(); iter != bi.rend(); ++iter){cout << *iter;} }void PrintNumberAdd(const BigInteger& a, const BigInteger& b) {auto ret = addTwoNumber(a, b);PrintNumber(a);cout << " add ";PrintNumber(b);cout << " is equal ";PrintNumber(ret);cout << "." << endl; }四、測試結果
?
代碼如下(網上的代碼看上去比較簡潔,但是并沒有拆分步驟,而是在循環內多次進行判斷和求和,我的代碼效率必然會更快一些,不過不是數量級的變化):
//2.兩數之和#include <list> #include <iostream> using namespace std;typedef list<int> BigInteger;BigInteger addTwoNumber(const BigInteger& a, const BigInteger& b) {BigInteger ret;const BigInteger* bi_s;const BigInteger* bi_l;//區分長短鏈if (a.size() > b.size()){bi_l = &a;bi_s = &b;}else{bi_l = &b;bi_s = &a;}//取較小長度int length = bi_s->size();//0為短鏈auto iter0 = bi_s->begin();auto iter1 = bi_l->begin();//是否進位標記bool carry = false;//遍歷完短鏈for (int i = 0; i != length; ++i){//求和int sum = *iter0 + *iter1;//如果上次遍歷結果進位,則加1if (carry) ++sum;if (sum < 10)carry = false;//否則不進位else{//如果結果大于等于10,則進位(標記進位,下次循環使用)sum %= 10;carry = true;}ret.push_back(sum);++iter0;++iter1;}//再添加較長數字的剩余高位(考慮進位)for (; iter1 != bi_l->end(); ++iter1){if (carry){//進位則加1,同時還可能發生繼續進位int num = *iter1 + 1;if (num < 10)carry = false;elsenum %= 10;ret.push_back(num);}else{ret.push_back(*iter1);carry = false;}}//最后進位可能if (carry){ret.push_back(1);}return ret; }void PrintNumber(const BigInteger& bi) {//逆序打印for (auto iter = bi.rbegin(); iter != bi.rend(); ++iter){cout << *iter;} }void PrintNumberAdd(const BigInteger& a, const BigInteger& b) {auto ret = addTwoNumber(a, b);PrintNumber(a);cout << " add ";PrintNumber(b);cout << " is equal ";PrintNumber(ret);cout << "." << endl; }int main() {//test0list<int> a = { 1,1,2,4,0,0,0,0 };//4211list<int> b = { 0,4,8,5,1,7 };//715840//求和并打印PrintNumberAdd(a, b);//test1a = { 1,2,3,4,5,6,7,8,9 };//987654321b = { 4,4,4,4 };//4444//求和并打印PrintNumberAdd(a, b);//test2a = { 2,5,9,0,0,0,1 };//1000925b = { 6,7 };//76//求和并打印PrintNumberAdd(a, b);//test3a = { 9,9,9 };//999b = { 1,1,1 };//111//求和并打印PrintNumberAdd(a, b);//test4a = {};//b = {};////求和并打印PrintNumberAdd(a, b); }總結
以上是生活随笔為你收集整理的【LeetCode】2.两数相加的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【LeetCode】1.两数之和
- 下一篇: 【LeetCode】3.无重复字符串的最