推薦:82,66(java)
72(python)https://github.com/CBLBY/datawhale_algorithm_learning/blob/master/Task02.ipynb
理論部分
- 理解線性表的定義與操作。
- 實現順序表。
- 實現單鏈表、循環鏈表、雙向鏈表。
練習部分
一、 線性表相關定義
基礎:
數據結構: 是指數據元素的集合及元素間的相互關係和構造方法。
邏輯結構: 元素之間的相互關係(前後關係)是數據的邏輯結構。與存儲位置無關。
存儲結構: 數據元素及元素之間關係的存儲稱爲存儲結構(或物理結構)(指數據的邏輯結構在計算機存儲空間的存放形式。)
數據結構按照邏輯關係的不同分爲線性結構和非線性結構兩大類。
線性表(Linear List): 一個線性表是n(n≥0)個元素的有限序列,通常表示爲(a1,a2, …,an)。線性結構的特點是數據元素之間程序一種線性關係,即元素“一個接一個排列”。
補充: 線性表的存儲結構分爲順序存儲和鏈式存儲。
順序表: 利用順序存儲結構(即利用數組)實現的線性表。
鏈表(Linked list): 利用指針方式實現的線性表稱爲鏈表(單鏈表、循環鏈表、雙鏈表)。它不要求邏輯上相鄰的數據元素在物理位置上也相鄰,即:邏輯結構與物理結構可以相同也可以不相同。
單向鏈表(單鏈表): 每個結點只含有一個鏈域(指針域)的鏈表。即:利用單鏈域的方式存儲線性表的邏輯結構。
雙向鏈表(雙鏈表): 每個結點含有兩個鏈域(指針域)的鏈表,分別指出當前元素的直接前驅和直接後驅。即:利用雙鏈域的方式存儲線性表的邏輯結構。
循環鏈表: 是一種首尾相連的單鏈表。即:在單鏈表(或雙鏈表)中,將尾結點的指針域改爲指向pHead,就得到循環鏈表。
鏈表本身是一種無序的數據結構,元素的插入和刪除不能保證順序性。
有序鏈表:
分不分有序單鏈表,有序雙鏈表?
有序鏈表的有序指順序還是指值的大小?
有序 通常是針對標準順序來說的,而標準順序比如我們自然數由小到大的順序就是標準順序。有序鏈表主要是值其存的值 從頭結點開始 跟標準順序一致 小的在前面 大的在後面。
有序是指鏈表中存的值,從頭結點開始由小到大排序。
單鏈表和雙鏈表的區分在指針域的個數上面,單鏈表只有一個指針域存儲後繼結點的指針,雙鏈表有兩個指針域一個存後繼節點的指針,另一存前驅節點的指針。
- 合併兩個有序鏈表
https://leetcode-cn.com/problems/merge-two-sorted-lists/
將兩個有序鏈表合併爲一個新的有序鏈表並返回。新鏈表是通過拼接給定的兩個鏈表的所有節點組成的。
示例:
輸入:1->2->4, 1->3->4
輸出:1->1->2->3->4->4
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
#先考慮鏈表其中一個爲空的情況
if not l1:
return l2
if not l2:
return l1
curNode1 = l1
curNode2 = l2
#先選出第一個節點
if curNode1.val < curNode2.val:
head = curNode1
curNode1 = curNode1.next
else:
head = curNode2
curNode2 = curNode2.next
cur = head
while curNode1 and curNode2:
if curNode1.val < curNode2.val:
cur.next = curNode1
curNode1 = curNode1.next
else:
cur.next = curNode2
curNode2 = curNode2.next
cur = cur.next
#一直循環到有一個鏈表先結束
#如果是鏈表1先結束,則拼上鍊表2剩餘的那段
if not curNode1:
cur.next = curNode2
#如果是鏈表2先結束,則拼上鍊表1剩餘的那段
else:
cur.next = curNode1
return head
- 刪除鏈表的倒數第N個節點
https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/
給定一個鏈表,刪除鏈表的倒數第 n 個節點,並且返回鏈表的頭結點。
示例:
給定一個鏈表: 1->2->3->4->5, 和 n = 2.
當刪除了倒數第二個節點後,鏈表變爲 1->2->3->5.
說明:給定的 n 保證是有效的。
進階:你能嘗試使用一趟掃描實現嗎?
疑問:爲什麼快的要比慢的快n個節點?
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
dummy = ListNode(0)
dummy.next = head
fast, slow = dummy, dummy
for _ in range(n+1):
fast = fast.next
while fast != None:
fast = fast.next
slow = slow.next
slow.next = slow.next.next
return dummy.next
- 旋轉鏈表
https://leetcode-cn.com/problems/rotate-list/
給定一個鏈表,旋轉鏈表,將鏈表每個節點向右移動k個位置,其中k是非負數。
示例 1:
輸入: 1->2->3->4->5->NULL, k = 2
輸出: 4->5->1->2->3->NULL
解釋:
向右旋轉 1 步: 5->1->2->3->4->NULL
向右旋轉 2 步: 4->5->1->2->3->NULL
示例 2:
輸入: 0->1->2->NULL, k = 4
輸出: 2->0->1->NULL
解釋:
向右旋轉 1 步: 2->0->1->NULL
向右旋轉 2 步: 1->2->0->NULL
向右旋轉 3 步: 0->1->2->NULL
向右旋轉 4 步: 2->0->1->NULL
不懂了
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def rotateRight(self, head: ListNode, k: int) -> ListNode:
if head is None or head.next is None:
return head
fast = head
slow = head
p = head
newHead = None
count = 1
while p.next:
p = p.next
count += 1
# 看不懂了
k = k % count
while fast.next:
fast = fast.next
if k<=0:
slow = slow.next
k -= 1
fast.next = head
newHead = slow.next
slow.next = None
return newHead