2.兩數(shù)相加 [c++ and python]

題目:給定兩個非空鏈表來表示兩個非負(fù)整數(shù)瞳抓。位數(shù)按照逆序方式存儲,它們的每個節(jié)點只存儲單個數(shù)字伏恐。將兩數(shù)相加返回一個新的鏈表孩哑。
你可以假設(shè)除了數(shù)字 0 之外,這兩個數(shù)字都不會以零開頭翠桦。
示例:

輸入:[2,4,3]
   [5,6,4]
,
輸出:[7,0,8]
原因:342 + 465 = 807

輸入:[5]
   [5]
,
輸出:[0,1]
原因:5+5=10


分析:

  • 鏈表對應(yīng)結(jié)點相加時增加前一個結(jié)點的進(jìn)位臭笆,并保存下一個結(jié)點的進(jìn)位;除法得進(jìn)位秤掌,模得結(jié)果愁铺。
  • 兩個鏈表長度不一致時,要處理較長鏈表剩余的高位和進(jìn)位計算的值闻鉴;
  • 如果最高位計算時還產(chǎn)生進(jìn)位茵乱,則還需要添加一個額外結(jié)點。

c++ code 32ms:

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <sstream> //stringstream
using namespace std;

 //Definition for singly-linked list.
/*
注釋:     先CTRL+K孟岛,然后CTRL+C

取消注釋: 先CTRL+K瓶竭,然后CTRL+U
*/
 struct ListNode {
     int val;
    ListNode *next;
     ListNode(int x) : val(x), next(NULL) {}
 };

//notice: my submit 
class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        ListNode* l3 = new ListNode(0);
        ListNode* p = l1, *q = l2, *curr = l3;
        int cup = 0;
        while (p != NULL || q != NULL){
            int x = (p != NULL) ? p->val : 0;
            int y = (q != NULL) ? q->val : 0;
            int sum = x + y + cup;
            cup = sum / 10;
            curr->next = new ListNode(sum % 10);
            curr = curr->next;
            if (p != NULL)p = p->next;
            if (q != NULL)q = q->next;
        }
        if (cup>0){
            curr->next = new ListNode(cup);
            curr = curr->next;
        }
        return l3->next;
    }

};

//修剪左 尾隨空格
void trimLeftTrailingSpaces(string &input) {
    input.erase(input.begin(), find_if(input.begin(), input.end(), [](int ch) {
        return !isspace(ch);
    }));
}
//修剪右 尾隨空格
void trimRightTrailingSpaces(string &input) {
    input.erase(find_if(input.rbegin(), input.rend(), [](int ch) {
        return !isspace(ch);
    }).base(), input.end());
}

vector<int> stringToIntegerVector(string input) {
    vector<int> output;
    trimLeftTrailingSpaces(input);
    trimRightTrailingSpaces(input);
    input = input.substr(1, input.length() - 2);
    stringstream ss;
    ss.str(input);
    string item;
    char delim = ',';
    while (getline(ss, item, delim)) {
        output.push_back(stoi(item));
    }
    return output;
}

ListNode* stringToListNode(string input) {
    // Generate list from the input
    vector<int> list = stringToIntegerVector(input);

    // Now convert that list into linked list
    ListNode* dummyRoot = new ListNode(0);
    ListNode* ptr = dummyRoot;
    for (int item : list) {
        ptr->next = new ListNode(item);
        ptr = ptr->next;
    }
    ptr = dummyRoot->next;
    delete dummyRoot;
    return ptr;
}

string listNodeToString(ListNode* node) {
    if (node == nullptr) {
        return "[]";
    }

    string result;
    while (node) {
        result += to_string(node->val) + ", ";
        node = node->next;
    }
    return "[" + result.substr(0, result.length() - 2) + "]";
}

int main() {
    string s;
    while (getline(cin, s)) {
        ListNode* l1 = stringToListNode(s);
        getline(cin, s);// 讀取換行
        ListNode* l2 = stringToListNode(s);

        ListNode* ret = Solution().addTwoNumbers(l1, l2);

        string out = listNodeToString(ret);
        cout << out << endl;
    }
    return 0;
}
測試c++





python code:

  • 和上面的思路不一樣,參考了目前最快c++ 20ms 提交的代碼,改成python運行了200ms渠羞。
import json
# Definition for singly-linked list.
class ListNode(object):
    def __init__(self, x):
        self.val = x
        self.next = None

# notice: submit
class Solution(object):
    def addTwoNumbers(self, l1, l2):
        """
        :type l1: ListNode
        :type l2: ListNode
        :rtype: ListNode
        """
        curr=ListNode(0)
        headl3=curr
        
        while l1 or l2:

            if l1:
                curr.val+=l1.val
            if l2:
                curr.val+=l2.val
            if l1.next or l2.next or curr.val>9:
                curr.next=ListNode(0)
                if curr.val>9:
                    curr.next.val+=1
                    curr.val-=10
                if l1.next:
                    l1=l1.next
                else:
                    '''[5][5]此例在死循環(huán)斤贰,以下兩處else考慮l1.next不存在
                    但是還存在回到上面第一個if處加l1.val'''
                    l1.val=0
                if l2.next:
                    l2=l2.next
                else:
                    l2.val=0

            else: 
                break 
            curr=curr.next
        return headl3  
  
    
    

def stringToIntegerList(input):
    return json.loads(input)

def stringToListNode(input):
    # Generate list from the input
    numbers = stringToIntegerList(input)

    # Now convert that list into linked list
    dummyRoot = ListNode(0)
    ptr = dummyRoot
    for number in numbers:
        ptr.next = ListNode(number)
        ptr = ptr.next

    ptr = dummyRoot.next
    return ptr

def listNodeToString(node):
    if not node:
        return "[]"

    result = ""
    while node:
        result += str(node.val) + ", "
        node = node.next
    return "[" + result[:-2] + "]"

def main():
    import sys
    def readlines():
        for line in sys.stdin:
            yield line.strip('\n')

    lines = readlines()
    while True:
        try:
            line = next(lines)
            l1 = stringToListNode(line)
            line = next(lines)
            l2 = stringToListNode(line)
            
            ret = Solution().addTwoNumbers(l1, l2)

            out = listNodeToString(ret)
            print(out)
        except StopIteration:
            break

if __name__ == '__main__':
    main()
測試python

在貼一個python( 104ms ) 目前提交最快的,我轉(zhuǎn)成c++反而更慢了 ┏┛┗┓
(c++573ms)

  • 思想:盡量不創(chuàng)建節(jié)點直接用現(xiàn)有的結(jié)點
class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        //ListNode* l3 = new ListNode(0);
        ListNode* p = l1, *q = l2, *curr = NULL;
        int cup = 0;
        while (p &&q )
        {
            int x = (p != NULL) ? p->val : 0;
            int y = (q != NULL) ? q->val : 0;
            int sum = x + y + cup;
            cup = sum / 10;
            p->val = sum % 10;
            curr = p;
            if (p != NULL)p = p->next;
            if (q != NULL)q = q->next;
        }
        while (p)
        {
            p->val = p->val + cup;
            cup = (p->val) / 10;
            p->val = p->val % 10;
            curr = p;
            p = p->next;
        }
        if (q)
        {
            //p一直記錄著添加的節(jié)點
            curr->next = q;
        
        }

        while (q)
        {
            q->val = q->val + cup;
            cup = (q->val) / 10;
            q->val = q->val % 10;
            curr = q;
            q = q->next;
        }
        if (cup > 0)
        {
            curr->next = new ListNode(cup);
            curr = curr->next;
        }
        return l1;
    }

};
測試c++





c++小白記錄

  1. 下面函數(shù)理解分別從左右各兩端消除輸入時空格
//erase
void trimLeftTrailingSpaces(string &input) {
    input.erase(input.begin(), find_if(input.begin(), input.end(), [](int ch) {
        return !isspace(ch);
    }));
}

//修剪右 尾隨空格
void trimRightTrailingSpaces(string &input) {
    input.erase(find_if(input.rbegin(), input.rend(), [](int ch) {
        return !isspace(ch);
    }).base(), input.end());
}
  • find_if:參看手冊
    find_if(InputIterator first, InputIterator last, Predicate pred);

first:第一個位置
last:最后元素之后下一個元素的位置
Predicate pred:lambda表達(dá)式
返回:用于引用范圍[first,last] 中滿足謂詞(Predicate pred)所指定條件的元素

lambda組成

不理解的話次询,把示例代碼運行一遍(主要是區(qū)別find() ,find_if())荧恍。
code:

// cl.exe /W4 /nologo /EHsc /MTd
#include <vector>
#include <algorithm>
#include <iostream>
#include <string>

using namespace std;

template <typename S> void print(const S& s) {
    for (const auto& p : s) {
        cout << "(" << p << ") ";
    }
    cout << endl;
}

// Test std::find()
template <class InputIterator, class T>
void find_print_result(InputIterator first, InputIterator last, const T& value) {

    // call <algorithm> std::find()
    auto p = find(first, last, value);

    cout << "value " << value;
    if (p == last) {
        cout << " not found." << endl;
    }
    else {
        cout << " found." << endl;
    }
}

// Test std::find_if()
template <class InputIterator, class Predicate>
void find_if_print_result(InputIterator first, InputIterator last,
    Predicate Pred, const string& Str) {

    // call <algorithm> std::find_if()
    auto p = find_if(first, last, Pred);

    if (p == last) {
        cout << Str << " not found." << endl;
    }
    else {
        cout << "first " << Str << " found: " << *p << endl;
    }
}

// Function to use as the UnaryPredicate argument to find_if() in this example
bool is_odd_int(int i) {
    return ((i % 2) != 0);
}

int main()
{
    // Test using a plain old array.
    const int x[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    cout << "array x[] contents: ";
    print(x);
    // Using non-member std::begin()/std::end() to get input iterators for the plain old array.
    cout << "Test std::find() with array..." << endl;
    find_print_result(begin(x), end(x), 10);
    find_print_result(begin(x), end(x), 42);
    cout << "Test std::find_if() with array..." << endl;
    find_if_print_result(begin(x), end(x), is_odd_int, "odd integer"); // function name
    find_if_print_result(begin(x), end(x), // lambda
        [](int i){ return ((i % 2) == 0); }, "even integer");

    // Test using a vector.
    vector<int> v;
    for (int i = 0; i < 10; ++i) {
        v.push_back((i + 1) * 10);
    }
    cout << endl << "vector v contents: ";
    print(v);
    cout << "Test std::find() with vector..." << endl;
    find_print_result(v.begin(), v.end(), 20);
    find_print_result(v.begin(), v.end(), 12);
    cout << "Test std::find_if() with vector..." << endl;
    find_if_print_result(v.begin(), v.end(), is_odd_int, "odd integer");
    find_if_print_result(v.begin(), v.end(), // lambda
        [](int i){ return ((i % 2) == 0); }, "even integer");
}

result:


示例結(jié)果

所以

  • find_if(input.begin(), input.end(), [](int ch) { return !isspace(ch); })表示找到字符串里按照begin-end方向第一個非空格位置。

  • find_if(input.rbegin(), input.rend(), [](int ch) { return !isspace(ch); }).base()表示找到字符串里按照rbegin-rend方向第一個非空格位置屯吊。

  • 補(bǔ)充:調(diào)用reverse_iterator的base成員函數(shù)可以產(chǎn)生“對應(yīng)的”iterator送巡,由于所有的 erase 函數(shù)都只接受正向迭代器 iterator,所以在進(jìn)行反向遍歷刪除元素時盒卸,首先需要將 reverse_iterator 轉(zhuǎn)換為 iterator骗爆,在這里我只說明一點,兩者相差一個元素蔽介,從一個反向迭代器獲得對應(yīng)的正向迭代器需要使用 base() 方法摘投。如下圖所示:ri 是指向元素3的反向迭代器,而 iri.base() 所得到的正想迭代器虹蓄。詳細(xì)解釋犀呼。

    base()函數(shù)效果

  • begin() 返回指向指向vector起始位置迭代器
    end() 返回指向當(dāng)前vector末尾元素的下一位置的迭代器
    rbegin() 返回指向當(dāng)前 vector 對象中最后一個元素的逆序迭代器。
    rend() 返回逆序迭代器武花,它指向當(dāng)前 vector 對象的第一個元素前面的位置

比較 begin/end 和 rbegin/rend 迭代器
  • 最后測了很多例子圆凰,才弄明白。
  • 總結(jié)
    • string::erase(begin,end) 函數(shù)不刪除end處的值. 平常erase的end都是一個字符串最后一個字符的下一個位置体箕,所以確實刪除了整個字符串专钉。

    • (rbegin-rend方向第一個非空格位置).base()代表后一個位置的值



  • 可以在 stringToIntegerVector函數(shù)中挑童,處理完trimLeftTrailingSpace和trimRightTrailingSpace后添加cout << input << input.length() << endl;測試一番得到下面的例子:
    測試左右函數(shù)處理
    • substr(1, input.length() - 2);// 結(jié)合2的結(jié)果,就好理解去除兩端[ ]所剩子串



4.如何理解:基于“stringstream+getline”實現(xiàn)字符串分割

stringstream ss;
    ss.str(input);
    string item;
    char delim = ',';
    while (getline(ss, item, delim)) {
        output.push_back(stoi(item));
    }

getline()
這里沒有count,
實現(xiàn)getline(有字符串流跃须,得到字符串站叼,分隔符)
stringstream







參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市菇民,隨后出現(xiàn)的幾起案子尽楔,更是在濱河造成了極大的恐慌,老刑警劉巖第练,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件阔馋,死亡現(xiàn)場離奇詭異,居然都是意外死亡娇掏,警方通過查閱死者的電腦和手機(jī)呕寝,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來婴梧,“玉大人下梢,你說我怎么就攤上這事∪洌” “怎么了孽江?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長番电。 經(jīng)常有香客問我岗屏,道長,這世上最難降的妖魔是什么钧舌? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任担汤,我火速辦了婚禮涎跨,結(jié)果婚禮上洼冻,老公的妹妹穿的比我還像新娘。我一直安慰自己隅很,他們只是感情好撞牢,可當(dāng)我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著叔营,像睡著了一般屋彪。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上绒尊,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天畜挥,我揣著相機(jī)與錄音,去河邊找鬼婴谱。 笑死蟹但,一個胖子當(dāng)著我的面吹牛躯泰,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播华糖,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼麦向,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了客叉?” 一聲冷哼從身側(cè)響起诵竭,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎兼搏,沒想到半個月后卵慰,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡佛呻,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年呵燕,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片件相。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡再扭,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出夜矗,到底是詐尸還是另有隱情泛范,我是刑警寧澤,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布紊撕,位于F島的核電站罢荡,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏对扶。R本人自食惡果不足惜区赵,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望浪南。 院中可真熱鬧笼才,春花似錦、人聲如沸络凿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽絮记。三九已至摔踱,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間怨愤,已是汗流浹背派敷。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人篮愉。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓般眉,卻偏偏與公主長得像,于是被迫代替她去往敵國和親潜支。 傳聞我的和親對象是個殘疾皇子甸赃,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,592評論 2 353

推薦閱讀更多精彩內(nèi)容

  • 給定兩個非空鏈表來表示兩個非負(fù)整數(shù)。位數(shù)按照逆序方式存儲冗酿,它們的每個節(jié)點只存儲單個數(shù)字埠对。將兩數(shù)相加返回一個新的鏈表...
    代碼守望者閱讀 1,737評論 0 0
  • 一些概念 數(shù)據(jù)結(jié)構(gòu)就是研究數(shù)據(jù)的邏輯結(jié)構(gòu)和物理結(jié)構(gòu)以及它們之間相互關(guān)系,并對這種結(jié)構(gòu)定義相應(yīng)的運算裁替,而且確保經(jīng)過這...
    Winterfell_Z閱讀 5,779評論 0 13
  • (一)LeetCode206.反轉(zhuǎn)鏈表 題目描述: 反轉(zhuǎn)一個單鏈表项玛。 代碼實現(xiàn) (二)LeetCode160. 相...
    Jarily閱讀 1,408評論 0 5
  • 萬圣節(jié)的裝扮不錯啊,這還是我嗎y( ˙?. )耶~
    簡之如素閱讀 134評論 0 0
  • 今天有位曾經(jīng)在日本留學(xué)的朋友說弱判,當(dāng)我在工作坊中談及父母幫忙收拾行李的時候襟沮,他非常有共鳴。茶山是2006年去韓國的昌腰,...
    茶山閱讀 732評論 0 1