日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

两数相加c++_LeetCode 热题 HOT 100(01,两数相加)

發布時間:2023/12/19 c/c++ 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 两数相加c++_LeetCode 热题 HOT 100(01,两数相加) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

LeetCode 熱題 HOT 100(01,兩數相加)

不夠優秀,發量尚多,千錘百煉,方可成佛。

算法的重要性不言而喻,無論你是研究者,還是最近比較火熱的IT 打工人,都理應需要一定的算法能力,這也是面試的必備環節,算法功底的展示往往能讓面試官眼前一亮,這也是在大多數競爭者中脫穎而出的重要影響因素。

然而往往大多數人比較注重自身的實操能力,著重于對功能的實現,卻忽視了對算法能力的提高。有的時候采用不同的算法來解決同一個問題,運行效率相差還是挺大的,畢竟我們最終還是需要站在客戶的角度思考問題嘛,能給用戶帶來更加極致的體驗當然再好不過了。

萬法皆空,因果不空。Taoye之前也不怎么情愿花費太多的時間放在算法上,算法功底也是相當的薄弱。這不,進入到了一個新的學習階段,面對導師的各種“嚴刑拷打”和與身邊人的對比,才開始意識到自己“菜”的事實。

講到這,流下了沒技術的眼淚!!!

這次的題目是LeeTCode 熱題 HOT 100的第二題,難度屬于中等,涉及到了鏈表的知識。

自打接觸Python以來,都沒有從中用到過鏈表,也無法通過指針來操作鏈表。曾經也只是在備考408,學習C的過程中刷過一些鏈表相關算法,一開始拿到這道題的時候,不知道Python如何下手,不知道怎么操作鏈表,菜是原罪(ノへ ̄、)

查找資料之后才發現,我們操作鏈表的時候其實就是將其封裝成一個實例對象,而實例對象中存儲了節點的相關信息(其實和C中差不多)。但與C或C++中不同的是,Python沒有指針,也就沒有什么指向操作,所以從對鏈表的整體結構理解上,Python和C、C++還是有點區別的。意思類似下圖:

可以理解成一種俄羅斯套娃的形式。

注意:只是理解上有所區別,其實表達的意思還是一樣的。

下面,我們就來看看這道題吧。

題目:兩數相加

給出兩個 非空 的鏈表用來表示兩個非負的整數。其中,它們各自的位數是按照 逆序 的方式存儲的,并且它們的每個節點只能存儲 一位 數字。

如果,我們將這兩個數相加起來,則會返回一個新的鏈表來表示它們的和。

您可以假設除了數字 0 之外,這兩個數都不會以 0 開頭。

示例

輸入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
輸出:7 -> 0 -> 8
原因:342 + 465 = 807

思路

前面也提到了,在Python中,鏈表可以理解成一種套娃的形式,通過輸入兩個鏈表,輸出一個新的鏈表,新鏈表中的每個節點的產生過程基本一致,所以我們初步判斷通過遞歸的方法來解決該問題。

當然了,遞歸能解決的問題,非遞歸同樣可以,只是將一次遞歸函數的調用替換成一次循環。所以下面將分別介紹兩種方法。

  • 方法一:遞歸

題中給出的例子里的兩個鏈表的長度是一樣的,但題意所表明的意思是任意長度的兩個鏈表。所以,為了提高算法的“泛化性能”,在輸入兩個長度不同鏈表的前提下,我們需要對其進行一個統一,就是對長度短的鏈表我們需要做一個補0處理。補0并不影響求和操作,但又方便了我們對截止遞歸的判斷。

這種處理方式在數學上還是挺常見的,比如說在求最值的時候,我們常常會用到均值不等式,但題目中給出的數值維數可能并不會明顯地滿足均值不能式,所以常常會用到一個擴維的操作,很巧妙的將題目向均值不等式靠近,從而簡化了對題目的解答,比如下面這道題的巧妙解答:

最后,左右同開5次方,再同乘27即可證畢。

回到算法題吧。

題目既然要我們求鏈表所對應的單位數之和,那么肯定會涉及進位,我們不妨將進位表達為carry。至此,我們不難想到,每次的遞歸需要的參數有三個,分別是第一個鏈表中的值、第二個鏈表中的值、上一次進位的值(非0即1)。

前面也有說到,在Python中,鏈表其實就是一個對象,而該對象中又有倆個屬性,分別是val和next,而next本身有代表一個鏈表對象。所以我們遞歸方法傳入的第一、第二個參數可以用當前鏈表節點所獲取到。

判斷跳出遞歸的條件:前面,我們已經對鏈表進行處理過了,也就是說無論你輸入的兩個鏈表長度是否一致,我們都對其進行了統一長度的處理。所以說當我們所傳入的三個參數同時為False的時候即可跳出遞歸。舉例說明: 1、輸入兩個空鏈表和一個carry為1的參數,說明已經產生了進位,此時我們需要對其進行處理,而非跳出遞歸。2、輸入的一個鏈表節點value值為5,而另一個節點為None,carry為0,此時我們依然需要進行求和處理,即使另一個節點為None,但我們已經對其進行了補0處理。3、至于其他可能性,各位看官可自行思考。

求和處理:

  • 求出兩個鏈表當前value值和carry的和,并對10進行一個divmod操作。說明: Python中divmod會返回一個元組,第一個值為進位,第二個值為取余,比如divmod(13, 10) = (1, 3)。注意:在求和的過程中,有可能當前節點為None,這個時候則需要將節點的value值作為0進行求和。

  • 實例化一個鏈表,也就是我們的目標返回鏈表,其value值為上述的取余。注意:這里一定理解清楚題意,鏈表中的值是實際值的逆序。

  • result的next屬性所對應的值本身又是一個鏈表,而對其進行賦值的時候,我們需要調用遞歸方法。傳遞的三個參數:經過上述過程,鏈表中的當前值已經處理完畢,這個時候需要處理鏈表的下一個值,也就是將下一個節點作為參數進行一次遞歸。但這里需要考慮的是,假如我們的當前節點為空,也就是說當前鏈表已經遍歷結束,則需要傳遞None給遞歸函數。

  • 相關代碼:

    class?Solution:
    ????def?recursion(self,?list_node1,?list_node2,?carry):
    ????????#?判斷跳出遞歸的條件
    ????????if?(list_node1?==?None)?and?(list_node2?==?None)?and?(carry?==?0):?return?None
    ????????#?兩個節點值和進位值的求和操作,若傳入的節點為None,則需要將value賦值為0進行求和,也就是補0
    ????????sum_number?=?(list_node1.val?if?list_node1?else?0)?+?(list_node2.val?if?list_node2?else?0)?+?carry
    ????????#?產生新的carry進位值,作為下一次遞歸的判斷。
    ????????carry,?value?=?divmod(sum_number,?10)
    ????????#?實例新的節點(result,為返回的目標節點的),其val屬性為value
    ????????result?=?ListNode(value)????
    ????????#?進行下一次遞歸
    ????????result.next?=?self.recursion(list_node1.next?if?list_node1?else?None,?list_node2.next?if?list_node2?else?None,?carry)
    ????????return?result

    ????#?主函數
    ????def?addTwoNumbers(self,?l1:?ListNode,?l2:?ListNode)?->?ListNode:
    ????????return?self.recursion(l1,?l2,?0)????#?執行入口,調用遞歸函數,傳入初試的兩個節點,默認進位為0
    • 方法二:非遞歸

    非遞歸的思想和遞歸差不多,只是除了返回result鏈表之外,還需要額外創建一個新的鏈表用于循環。

    class?Solution:
    ????def?addTwoNumbers(self,?l1:?ListNode,?l2:?ListNode)?->?ListNode:
    ????????#?初始node,result為返回結果鏈表,temp_node用作循環遍歷,鏈接產生新的節點
    ????????result?=?temp_node?=?ListNode(0)????
    ????????carry?=?0???#?初始進位為0
    ????????while?l1?or?l2?or?carry:????#?跳出循環的條件和遞歸一樣,三者同時為False的時候跳出循環
    ????????????#?兩個節點值和進位值的求和操作,若傳入的節點為None,則需要將value賦值為0進行求和,也就是補0
    ????????????sum_number?=?(l1.val?if?l1?else?0)?+?(l2.val?if?l2?else?0)?+?carry
    ????????????#?l1和l2當前節點操作完畢,指向下一個節點,準備進入下一次循環
    ????????????l1?=?l1.next?if?l1?else?None;?l2?=?l2.next?if?l2?else?None
    ????????????#?產生新的carry進位值,作為下一次遞歸的判斷。
    ????????????carry,?value?=?divmod(sum_number,?10)
    ????????????#?重新賦值temp_node節點,不斷為result鏈表進行延伸補充節點
    ????????????temp_node.next?=?ListNode(value);?temp_node?=?temp_node.next
    ????????return?result.next

    總的來說,非遞歸表達的思想和遞歸差不多。

    不過這里有一點值得說明下: result節點只在初始和最后返回時用到過,而在算法的核心while循環中并沒有用到,為什么還能返回正常的result鏈表呢?

    這主要是因為,我們初始化創建的result已經和temp_node都賦值給新的鏈表了,其中val為0,next屬性值為None,其內存位置是固定的。而初試的result和temp_node是相等的,所指向的內存地址是一樣的,所以我們只需要的延伸temp_node節點即可,而result地址不變,而result指向的下一個節點的地址則會隨著temp_node的變化而變化。

    注意: result的內存地址從始至終都是不變的,初試的時候和temp_node的地址是一樣,只不過之后變化的是temp_node,而result不變。我們可以在通過如下操作簡單測試下這個過程:

    也不知道自己表述清楚了沒有?

    也不知道各位看官理解了沒有?

    如果沒看懂的話,強烈建議重新看一遍,細細琢磨下,這個地方還是挺重要的。

    • 最后

    在逛討論區的時候,看到了另外一種解法,感覺這算法寫的挺優雅的,在這里分享下。

    """
    ??? Author:學廢了的Kai
    """
    class?Solution:
    ????def?addTwoNumbers(self,?l1:?ListNode,?l2:?ListNode)?->?ListNode:
    ????????head?=?curr?=?ListNode()
    ????????carry?=?val?=?0
    ????????while?carry?or?l1?or?l2:
    ????????????val?=?carry
    ????????????if?l1:?l1,?val?=?l1.next,?l1.val?+?val
    ????????????if?l2:?l2,?val?=?l2.next,?l2.val?+?val
    ????????????carry,?val?=?divmod(val,?10)
    ????????????curr.next?=?curr?=?ListNode(val)
    ????????return?head.next

    這種解法和上面非遞歸表達的是同種思想,只不過在求sum的時候這個是疊加的形式,而非一次性求和。上面算法還有一點值得學習的是,在最后curr.next = curr = ListNode(val)這行代碼中,其表達的意思是如下:

    curr.next?=ListNode(val)
    curr?=?curr.next

    Taoye也不知道為什么是這種賦值順序,按道理講應該是先賦值curr = ListNode(val),再賦值curr.next = curr?但經過測試之后,上述兩行代碼塊才是正確的,暫時不知道為什么,之后有機會再回過頭看看吧。

    我是Taoye,研究生在讀。愛專研,愛分享,熱衷于各種技術,學習之余喜歡下象棋、聽音樂、聊動漫,希望借此一畝三分地記錄自己的成長過程以及生活點滴,也希望能結實更多志同道合的圈內朋友,更多內容歡迎來訪微信公主號:玩世不恭的Coder

    推薦閱讀:

    LeetCode 熱題 HOT 100(00,兩數之和)
    Taoye滲透到一家黑平臺總部,背后的真相細思極恐
    《大話數據庫》-SQL語句執行時,底層究竟做了什么小動作?
    那些年,我們玩過的Git,真香
    基于Ubuntu+Python+Tensorflow+Jupyter notebook搭建深度學習環境
    網絡爬蟲之頁面花式解析
    手握手帶你了解Docker容器技術
    一文詳解Hexo+Github小白建站
    打開ElasticSearch、kibana、logstash的正確方式

    總結

    以上是生活随笔為你收集整理的两数相加c++_LeetCode 热题 HOT 100(01,两数相加)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。