LeetCode刷題總結-鏈表


LeetCode刷題總結-鏈表

一、鏈表

    鏈表分為單向鏈表、單向循環鏈表和雙向鏈表,一下以單向鏈表為例實現單向鏈表的節點實現和單鏈表的基本操作。

    單向鏈表

單向鏈表也叫單鏈表,是鏈表中最簡單的一種形式,它的每個節點包含兩個域,一個信息域(元素域)和一個鏈接域。這個鏈接指向鏈表中的下一個節點,而最后一個節點的鏈接域則指向一個空值。

 

  • 表元素域elem用來存放具體的數據;
  • 鏈接域next用來存放下一個節點的位置(python中的標識);
  • 變量p指向鏈表的頭節點(首節點)的位置,從p出發能找到表中的任意節點;

 

    節點實現

class SingleNode(object): """單鏈表的結點""" def __init__(self,item): # _item存放數據元素 self.item = item # _next是下一個節點的標識 self.next = None

    單鏈表的操作

 

  • is_empty() 鏈表是否為空;
  • length() 鏈表長度;
  • travel() 遍歷整個鏈表;
  • add(item) 鏈表頭部添加元素;
  • append(item) 鏈表尾部添加元素;
  • insert(pos, item) 指定位置添加元素;
  • remove(item) 刪除節點;
  • search(item) 查找節點是否存在;

 

 

class SingleLinkList(object): """單鏈表"""
    def __init__(self): self._head = None def is_empty(self): """判斷鏈表是否為空"""
        return self._head == None def length(self): """鏈表長度"""
        # cur初始時指向頭節點
        cur = self._head count = 0 # 尾節點指向None,當未到達尾部時
        while cur != None: count += 1
            # 將cur后移一個節點
            cur = cur.next return count def travel(self): """遍歷鏈表""" cur = self._head while cur != None: printcur.item) cur = cur.next
     
    def add(self, item): """頭部添加元素"""
        # 先創建一個保存item值的節點
        node = SingleNode(item) # 將新節點的鏈接域next指向頭節點,即_head指向的位置
        node.next = self._head # 將鏈表的頭_head指向新節點
        self._head = node def append(self, item): """尾部添加元素""" node = SingleNode(item) # 先判斷鏈表是否為空,若是空鏈表,則將_head指向新節點
        if self.is_empty(): self._head = node # 若不為空,則找到尾部,將尾節點的next指向新節點
        else: cur = self._head while cur.next != None: cur = cur.next cur.next = node def insert(self, pos, item): """指定位置添加元素"""
        # 若指定位置pos為第一個元素之前,則執行頭部插入
        if pos <= 0: self.add(item) # 若指定位置超過鏈表尾部,則執行尾部插入
        elif pos > (self.length()-1): self.append(item) # 找到指定位置
        else: node = SingleNode(item) count = 0 # pre用來指向指定位置pos的前一個位置pos-1,初始從頭節點開始移動到指定位置
            pre = self._head while count < (pos-1): count += 1 pre = pre.next # 先將新節點node的next指向插入位置的節點
            node.next = pre.next # 將插入位置的前一個節點的next指向新節點
            pre.next = node def remove(self,item): """刪除節點""" cur = self._head pre = None while cur != None: # 找到了指定元素
            if cur.item == item: # 如果第一個就是刪除的節點
                if not pre: # 將頭指針指向頭節點的后一個節點
                    self._head = cur.next else: # 將刪除位置前一個節點的next指向刪除位置的后一個節點
                    pre.next = cur.next break
            else: # 繼續按鏈表后移節點
                pre = cur cur = cur.next def search(self,item): """鏈表查找節點是否存在,並返回True或者False""" cur = self._head while cur != None: if cur.item == item: return True cur = cur.next return False if __name__ == "__main__": ll = SingleLinkList() ll.add(1) ll.add(2) ll.append(3) ll.insert(2, 4) print "length:",ll.length() ll.travel() print ll.search(3) print ll.search(5) ll.remove(1) print "length:",ll.length() ll.travel()

 

 

 

二、LeetCode相關題目

2.  兩數之和

題意:給出兩個非空的鏈表用來表示兩個非負的整數。其中,它們的各自的位數是按照逆序方式存儲的,並且它們的每個節點只能存儲一位數字,如果我們將這兩個數相加起來,則會返回一個新的鏈表來表示它們的和。你可以假設出了數字0之外,這兩個數都不會以0開頭。

思路:此題為鏈表的基礎題,給出的l1,l2兩個鏈表表示的位數按照逆序排序,計算兩個列表的和就和筆算兩個數字的加法原理一樣,首先計算個位,把計算的個位數存儲,十位數進行進位;當下一個循環時,把上次的進位和這次一起計算,以此類推,直到給出的兩個鏈表全部計算完。

 

# Definition for singly-linked list. # class ListNode(object): # def __init__(self, x): # self.val = x # self.next = None

class Solution(object): def addTwoNumbers(self, l1, l2): """ :type l1: ListNode :type l2: ListNode :rtype: ListNode """ temp = ListNode(0) l3 = temp a = 0 #當l1不為空或者l2不為空或者a不等於0的時候
        while l1 != None or l2 !=None or a != 0: if l1 : #a等於a加上l1當前的值
                a += l1.val #l1的指針指向下一個
                l1 = l1.next if l2 : a += l2.val l2 = l2.next #temp的下一個的值就是 a%10
            temp.next = ListNode(a%10) temp = temp.next a=a//10
        #l3代替temp來輸出鏈表
        return l3.next

 

 

 

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

題意:給定一個鏈表,刪除鏈表的倒數第n個節點,並返回鏈表的頭結點。

思路:1.遍歷兩遍,第一遍計算此列表一共有多少個節點,第二遍刪除第n個節點;

           2.定義兩個指針,兩個指針相差n個節點,當后面的指針遍歷完整個鏈表時,刪除前面指針的節點。

思路一:

思路二:

 

class Solution: def removeNthFromEnd(self, head, n): """ :type head: ListNode :type n: int :rtype: ListNode """ p = q = head for i in range(n): q = q.next   # 前面的指針先移動n個節點
        if not q:        # 如果移動n次正好是None,則說明次鏈表的長度就為n,應該直接去掉頭結點
            return head.next while q.next: p = p.next q = q.next p.next = p.next.next return head

 

 

 

21. 合並兩個有序鏈表

題意:將兩個有序鏈表合並為一個新的有序鏈表並返回。新鏈表是通過拼接給定的兩個鏈表的所有節點組成;

思路:此題為列表操作的基本題目,只需要比較兩個列表當前節點元素哪個更小,加入到定義好的鏈表中並向后移動指針;

 

class Solution: def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode: head = p = ListNode(-1)  # 任意定義一個頭結點
        while l1 and l2:         # 比較l1和l2節點元素的大小,小的節點加入到head節點中,並移動指針
            if l1.val < l2.val: p.next = l1 l1 = l1.next else: p.next = l2 l2 = l2.next p = p.next p.next = l1 if l1 else l2 return head.next      

 

23. 合並K個排序鏈表

題意:合並k個排序鏈表,返回合並后的排序鏈表。請分析和描述算法的復雜度;

思路:1. 暴力法,遍歷所有鏈表,獲得所有元素,將元素排序后,依次放在鏈表中;

           2.逐一比較,比較k個節點的元素,獲得最小值,添加到創建鏈表的最后;

思路一:

 

class Solution(object): def mergeKLists(self, lists): """ :type lists: List[ListNode] :rtype: ListNode """ nodes = [] head = point = ListNode(0) for l in lists: while l: nodes.append(l.val) l = l.next for x in sorted(nodes): point.next = ListNode(x) point = point.next return head.next

 

時間復雜度:O(NlogN),其中N是節點的總數目;

空間復雜度:O(N)。

思路二:

 

 

24. 兩兩交換鏈表中的節點

題意:給定一個鏈表,兩兩交換其中相鄰的節點,並返回交換后的節點。

思路:

 

class Solution: def swapPairs(self, head: ListNode) -> ListNode: dummy = p = ListNode(-1) p.next = head while p.next and p.next.next: a, b = p.next, p.next.next p.next = b a.next = b.next b.next = a p = a return dummy.next

 

 

 

25. K個一組翻轉鏈表

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM