算法(13)-leetcode-explore-learn-數據結構-鏈表小結

leetcode-explore-learn-數據結構-鏈表5

  • 1.小結
  • 2.例題
    • 2.1合并兩個有序鏈表
      • 思路1:迭代
      • 思路2:遞歸
    • 2.2 兩數相加
    • 2.3 扁平化多級雙向鏈表
    • 2.4 復制帶隨機指針的鏈表
    • 2.5 旋轉鏈表

本系列博文為leetcode-explore-learn子欄目學習筆記,如有不詳之處,請參考leetcode官網:https://leetcode-cn.com/explore/learn/card/linked-list/

所有例題的編程語言為python

1.小結

單鏈表雙鏈表的相同點:
1.無法在常量時間內隨意訪問數據
2.能夠在o(1)時間內,在給定節點之后完成新節點的添加
3.能夠在o(1)的時間內,刪除鏈表的第一節點

區別:刪除給定節點
單鏈表無法由給定節點獲取前一個節點,因此在刪除給定節點之前必須花費o(n)的時間來找出前一個節點
雙鏈表中,可以使用“prev”字段獲取前一個節點,因此能在o(1)的時間內=刪除給定節點。

鏈表的主要優勢:刪除添加節點十分方便

2.例題

2.1合并兩個有序鏈表

leetcode 21
將兩個升序鏈表合并為一個新的升序鏈表并返回。

思路1:迭代

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = Noneclass Solution(object):def mergeTwoLists(self, l1, l2):""":type l1: ListNode:type l2: ListNode:rtype: ListNode"""if l1==None or l2==None:return l1 if l1 else l2res_head=ListNode(0)res_curr_node=res_headwhile(l1 and l2):if l1.val<=l2.val:l1_next_node=l1.nextl1.next=Noneres_curr_node.next=l1l1=l1_next_noderes_curr_node=res_curr_node.nextelse:l2_next_node=l2.nextl2.next=Noneres_curr_node.next=l2l2=l2_next_noderes_curr_node=res_curr_node.nextif l1:res_curr_node.next=l1if l2:res_curr_node.next=l2return res_head.next    

精簡寫法:


class Solution(object):def mergeTwoLists(self, l1, l2):if l1==None or l2==None:return l1 if l1 else l2res_head=ListNode(0)res_curr_node=res_headwhile(l1 and l2):if l1.val<=l2.val:res_curr_node.next=l1l1=l1.nextelse:res_curr_node.next=l2l2=l2.nextres_curr_node=res_curr_node.nextres_curr_node.next=l1 if l1 else l2   return res_head.next

思路2:遞歸

遞歸最重要的是遞歸出口


class Solution(object):def mergeTwoLists(self, l1, l2):""":type l1: ListNode:type l2: ListNode:rtype: ListNode"""if l1==None:return l2elif l2==None:return l1elif l1.val<=l2.val:l1.next=self.mergeTwoLists(l1.next,l2)return l1       # 由頂向下時,已經決定了第一個節點是誰,遞歸得到最底端時,直接將長鏈表的剩余部分鏈接回已經排序好的鏈表中。else:l2.next=self.mergeTwoLists(l1,l2.next)return l2

2.2 兩數相加

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

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

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

思路:逆序存儲簡化了問題,直接遍歷兩個鏈表的對位元素,相加后維護一個進位標志flag。
冗余

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = Noneclass Solution(object):def addTwoNumbers(self, l1, l2):""":type l1: ListNode:type l2: ListNode:rtype: ListNode"""flag=0res_head=ListNode(0)res_cur_node=res_headwhile(l1 and l2):sum_num=l1.val+l2.val+flagflag=sum_num//10res_cur_node.next=ListNode(sum_num%10)res_cur_node=res_cur_node.nextl1=l1.nextl2=l2.nextwhile(l1):#print(l1.val)sum_num=l1.val+flagflag=sum_num//10res_cur_node.next=ListNode(sum_num%10)res_cur_node=res_cur_node.nextl1=l1.nextwhile(l2):#print(l2.val)sum_num=l2.val+flagflag=sum_num//10res_cur_node.next=ListNode(sum_num%10)res_cur_node=res_cur_node.nextl2=l2.nextif flag:res_cur_node.next=ListNode(flag)return res_head.next

精簡

class Solution(object):def addTwoNumbers(self, l1, l2):""":type l1: ListNode:type l2: ListNode:rtype: ListNode"""carry=0res_head=ListNode(0)res_cur_node=res_headwhile(l1 or l2 or carry):if l1:carry+=l1.vall1=l1.nextif l2:carry+=l2.vall2=l2.nextcarry,val=divmod(carry,10)res_cur_node.next=ListNode(val)res_cur_node=res_cur_node.nextreturn res_head.next

2.3 扁平化多級雙向鏈表

多級雙向鏈表中,除了指向下一個節點和前一個節點的指針外,它還有一個子鏈表指針,可能指單獨的雙向鏈表。這些子鏈表也可能有一個或多個自己的子項。一次類推,生成多級數據結構 。

給出位于鏈表第一級的頭節點,請扁平化鏈表,使所有的節點出現子啊單級雙鏈表中。

直覺:采用遞歸的方式求解,可每個節點該如何處理呢:
新建一個res_head,res_head下一個節點應該為curr_node.child,curr_node.next,

官方思路遞歸:扁平化處理可以看作對二叉樹進行先序遍歷,child作為二叉樹中的指向座子樹的left指針,next可以看作二叉樹中的right指針。
難點:深度優先遍歷到了末尾該如何讓扁平化操作?
flatten_dfs(prev, curr)接收兩個指針作為函數參數,并返回扁平化鏈表中的尾部指針。curr指向需要扁平化的子列表,prev指向curr元素的前一個元素。
在dfs函數中首先要建立prev和curr的雙向鏈接
然后對左子樹進行操作dfs(curr,cuur.child)其將返回扁平化子列表的尾部元素,再調用dfs(tail,curr.next)對右子樹進行操作。注意點:
1.在進行左子樹操作時,需要先保存curr.next的信息
2.在扁平化child指針所指向的列表之后,應該刪除child指針

"""
# Definition for a Node.
class Node(object):def __init__(self, val, prev, next, child):self.val = valself.prev = prevself.next = nextself.child = child
"""class Solution(object):def flatten(self, head):""":type head: Node:rtype: Node"""if head==None:return headdummy_head=Node(None,None,head,None)self.flatten_dfs(dummy_head,head)dummy_head.next.prev=Nonereturn dummy_head.nextdef flatten_dfs(self,prev,curr):if curr==None:return prevcurr.prev=prevprev.next=currtempNext=curr.nexttail=self.flatten_dfs(curr,curr.child)curr.child=Nonereturn self.flatten_dfs(tail,tempNext)

官方思路迭代:

2.4 復制帶隨機指針的鏈表

給定一個鏈表,每個節點包含一個額外增加的隨機指針,該指針可以指向鏈表中的任何節點或空節點
編程實現這個鏈表的深度拷貝

難點:新建節點,很簡單,隨機節點該如何指向?

先遍歷一遍形成一個單鏈表,再遍歷一遍原鏈表找到帶隨機指針的節點,在單鏈表中找到對應的節點,難的是對應節點怎么找,因為,指針存的是地址,在新鏈表中并不知道該指向哪一個?解決方案–維護一張map映射表,每個節點對應的新節點,因此便可以找到對應的節點。

"""
# Definition for a Node.
class Node:def __init__(self, x, next=None, random=None):self.val = int(x)self.next = nextself.random = random
"""class Solution(object):def copyRandomList(self, head):""":type head: Node:rtype: Node"""if head==None:return NonevisitedHash={}res_head=Node(0)res_cur_node=res_headcur_node=headwhile(cur_node):node=Node(cur_node.val,None,None)res_cur_node.next=nodevisitedHash[cur_node]=noderes_cur_node=res_cur_node.nextcur_node=cur_node.nextcur_node=headres_cur_node=res_head.nextwhile(cur_node):if cur_node.random:node=visitedHash[cur_node.random]res_cur_node.random=nodecur_node=cur_node.nextres_cur_node=res_cur_node.nextreturn res_head.next

參考官網給題解:遞歸
帶隨機指針的鏈表可以看作一張圖,要做的是遍歷整張圖,并拷貝它。拷貝的意思是每當遇到一個新的未訪問過的節點,需創造新的節點。在回溯的過程中記錄訪問過的節點,否則因為隨機指針存在,會導致死循環。

"""
# Definition for a Node.
class Node:def __init__(self, x, next=None, random=None):self.val = int(x)self.next = nextself.random = random
"""class Solution(object):def __init__(self):self.visitedHash={}def copyRandomList(self, head):""":type head: Node:rtype: Node"""if head==None:return Noneif head in self.visitedHash:return self.visitedHash[head]node=Node(head.val,None,None)self.visitedHash[head]=nodenode.next=self.copyRandomList(head.next)node.random=self.copyRandomList(head.random)return node

2.5 旋轉鏈表

給定一個鏈表,將鏈表的每個節點向右移動k個位置,其中k是非負數。

思路1:和旋轉數組一樣,每次右移一位,移動K次即可

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = Noneclass Solution(object):def rotateRight(self, head, k):""":type head: ListNode:type k: int:rtype: ListNode"""if head==None or head.next==None:return headl=0cur_node=headwhile(cur_node):l+=1cur_node=cur_node.nextk=k%ldef rotate_one_step(head):pre_pre_node=Nonepre_node=headcur_node=head.nextwhile(cur_node):pre_pre_node=pre_nodepre_node=cur_nodecur_node=cur_node.nextpre_pre_node.next=Nonepre_node.next=headreturn pre_nodewhile(k>0):head=rotate_one_step(head)k-=1return head         

思路2: 移動k次,就是將倒數的k個節點相對順序不變的移動到鏈表的頭部。所以從鏈表的head開始,往后找到L-k個節點,將后半部分移動到鏈表的前半部分。

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = Noneclass Solution(object):def rotateRight(self, head, k):""":type head: ListNode:type k: int:rtype: ListNode"""if head==None or head.next==None:return headl=0cur_node=headwhile(cur_node):l+=1cur_node=cur_node.nextk=k%l# 首尾相連pre_node=Nonecur_node=headwhile(cur_node):pre_node=cur_nodecur_node=cur_node.nextpre_node.next=head# 尋找切割點cur_node=headfor _ in range(1,l-k): #[0,l-k-1]cur_node=cur_node.next# 確定的新的頭部new_head=cur_node.nextcur_node.next=Nonereturn new_head

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/445035.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/445035.shtml
英文地址,請注明出處:http://en.pswp.cn/news/445035.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

leetcode121買賣股票的最佳時機

給定一個數組&#xff0c;它的第 i 個元素是一支給定股票第 i 天的價格。 如果你最多只允許完成一筆交易&#xff08;即買入和賣出一支股票&#xff09;&#xff0c;設計一個算法來計算你所能獲取的最大利潤。 注意你不能在買入股票前賣出股票。 示例 1: 輸入: [7,1,5,3,6,…

epoll的內核實現

epoll是由一組系統調用組成。 int epoll_create(int size); int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); int epoll_wait(int epfd, struct epoll_event *events,int maxevents, int timeout); select/poll的缺點在于&#xff1…

算法(14)-數據結構-二叉樹

leetcode-explore-learn-數據結構-二叉樹10.概述1.深度優先遍歷dfs1.1先序遍歷-中左右1.2中序遍歷-左中右1.3后序遍歷-左右中2.廣度優先遍歷bfs3.遍歷-常見問題3.1 二叉樹的最大深度自頂向下自底向上3.2對稱二叉樹3.3路徑總和4.重構-常見問題4.1根據中序和后序遍歷序列構造二叉…

多進程魚多線程的權衡選擇

最近有好多人在網上問道做游戲開發框架用多線程還是多進程呢,或者兩者之間的優缺點,等等類似的問題。下邊小高就帶您小小分析一下: 1、首先要明確進程和線程的含義:進程(Process)是具有一定獨立功能的程序關于某個數據集合上的一次運行活動,是系統進行資源分配和調度的一…

leetcode322 零錢兌換

給定不同面額的硬幣 coins 和一個總金額 amount。編寫一個函數來計算可以湊成總金額所需的最少的硬幣個數。如果沒有任何一種硬幣組合能組成總金額&#xff0c;返回 -1。 示例 1: 輸入: coins [1, 2, 5], amount 11 輸出: 3 解釋: 11 5 5 1 示例 2: 輸入: coins [2],…

給數據減肥 讓MySQL數據庫跑的更快

在數據庫優化工作中&#xff0c;使數據盡可能的小&#xff0c;使表在硬盤上占據的空間盡可能的小&#xff0c;這是最常用、也是最有效的手段之一。因為縮小數據&#xff0c;相對來說可以提高硬盤的讀寫速度&#xff0c;并且在查詢過程中小表的內容處理時所占用的系統資源比較少…

算法(15)-leetcode-explore-learn-數據結構-運用遞歸解決二叉樹的問題

leetcode-explore-learn-數據結構-二叉樹2本系列博文為leetcode-explore-learn子欄目學習筆記&#xff0c;如有不詳之處&#xff0c;請參考leetcode官網&#xff1a;https://leetcode-cn.com/explore/learn/card/data-structure-binary-tree/2/traverse-a-tree/7/

leetcode538 把二叉搜索樹轉換成累加樹

給定一個二叉搜索樹&#xff08;Binary Search Tree&#xff09;&#xff0c;把它轉換成為累加樹&#xff08;Greater Tree)&#xff0c;使得每個節點的值是原來的節點值加上所有大于它的節點值之和。 對于每一個點來說&#xff0c;自己的父&#xff0c;和自己父的右子樹都是大…

AWK常用命令華(1)

awk 調用: 1.調用awk:

AWk的調用精華

awk 的調用方式 awk 提供了適應多種需要的不同解決方案,它們是: 一、awk 命令行,你可以象使用普通UNIX 命令一樣使用awk,在命令行中你也可以使用awk 程序設計語言,雖然awk 支持多行的錄入,但是錄入長長的命令行并保證其正 確無誤卻是一件令人頭疼的事,因此,這種方法一般…

算法(16)-leetcode-explore-learn-數據結構-二叉樹總結

leetcode-explore-learn-數據結構-二叉樹3本系列博文為leetcode-explore-learn子欄目學習筆記&#xff0c;如有不詳之處&#xff0c;請參考leetcode官網&#xff1a;https://leetcode-cn.com/explore/learn/card/data-structure-binary-tree/2/traverse-a-tree/7/所有例題的編程…

leetcode15 三數之和

給定一個包含 n 個整數的數組 nums&#xff0c;判斷 nums 中是否存在三個元素 a&#xff0c;b&#xff0c;c &#xff0c;使得 a b c 0 &#xff1f;找出所有滿足條件且不重復的三元組。 注意&#xff1a;答案中不可以包含重復的三元組。 例如, 給定數組 nums [-1, 0, 1,…

AWK再次認識--內置的參數,以及編寫腳本

原本這是篇給公司內同事寫的培訓文章&#xff0c;對于初學awk的人還蠻有幫助&#xff0c;貼到這里與大家共享一下。 〇、前言 意見反饋&#xff0c;請mailto:datouwanggmail.com。 一、AWK簡介 AWK名字來源于三位創造者Aho、Weinberger和Kernighan統稱。 AWK擅長處理文本數據。…

AWk高級編程

首先再說一說awk的工作流程還是有必要的 : 執行awk時, 它會反復進行下列四步驟. 1. 自動從指定的數據文件中讀取一個數據行. 2. 自動更新(Update)相關的內建變量之值. 如 : NF, NR, $0... 3. 依次執行程序中所有 的 Pattern { Actions } 指令. 4. 當執行完程序中所有 Pattern {…

leetcode19. 刪除鏈表的倒數第N個節點

給定一個鏈表&#xff0c;刪除鏈表的倒數第 n 個節點&#xff0c;并且返回鏈表的頭結點。 示例&#xff1a; 給定一個鏈表: 1->2->3->4->5, 和 n 2. 當刪除了倒數第二個節點后&#xff0c;鏈表變為 1->2->3->5. 說明&#xff1a; 給定的 n 保證是有效…

python模塊(5)-Matplotlib 簡易使用教程

Matplotlib簡易使用教程0.matplotlib的安裝1.導入相關庫2.畫布初始化2.1 隱式創建2.2 顯示創建2.3 設置畫布大小2.4 plt.figure()常用參數3.plt. 能夠繪制圖像類型3.1等高線3.2 箭頭arrow4.簡單繪制小demodemo1.曲線圖demo2-柱狀、餅狀、曲線子圖5.plt.plot()--設置曲線顏色,粗…

random_shuffle 和transform算法

1)STL中的函數random_shuffle()用來對一個元素序列進行重新排序(隨機的),函數原型如下: std::random_shuffle

C語言字符輸出格式化

符號屬性 長度屬性 基本型 所占 位數 取值范圍 輸入符舉例 輸出符舉例 -- -- char 8 -2^7 ~ 2^7-1 %c %c、%d、%u signed -- char 8 -2^7 ~ 2^7-1 %c %c、%d、%u unsigned -- char 8 0 ~ 2^8-1 %c %c、%d、%u [signed] short [int] 16 -2^15 ~ 2^15-1 %hd %hd unsigned short […

leetcode20 有效的括號

給定一個只包括 (&#xff0c;)&#xff0c;{&#xff0c;}&#xff0c;[&#xff0c;] 的字符串&#xff0c;判斷字符串是否有效。 有效字符串需滿足&#xff1a; 左括號必須用相同類型的右括號閉合。 左括號必須以正確的順序閉合。 注意空字符串可被認為是有效字符串。 示…

python模塊(6)-Pandas 簡易使用教程

Pandas 簡易教程1.Pandas簡介2.創建2.1創建dataFrame2.2創建Series3.dataframe數據訪問3.1 獲取一列--列標簽3.2 獲取多列--列標簽列表3.3 獲取一行--行標簽.loc()3.4 獲取多行--行切片操作.loc()3.5 index 獲取行列信息--df.iloc()3.6 獲取一個元素3.7 布爾值選擇數據4.datafr…