今天開始抽空刷一些leetcode里數(shù)據(jù)結(jié)構(gòu)的題,在這里記錄下來。按難易程度開始刷吧。
第一次更新:2018.10.15
237、刪除鏈表中的節(jié)點
開始看題的時候有點懵,沒太懂題目意思,刪除鏈表中值為某個值的節(jié)點,但題目沒有給定鏈表。后來想了一會,直接用該鏈表的下一個節(jié)點覆蓋掉這個節(jié)點就可以了。
class Solution(object):
def deleteNode(self, node):
"""
:type node: ListNode
:rtype: void Do not return anything, modify node in-place instead.
"""
if node:
node.val = node.next.val
node.next = node.next.next
206、反轉(zhuǎn)鏈表
先用迭代實現(xiàn)
class Solution(object):
def reverseList(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
if not head:
return None
a, b, c = None, head, head.next
while c:
b.next = a
a, b, c = b, c, c.next
b.next = a
return b
再用遞歸
class Solution(object):
def reverseList(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
if not head:
return None
elif not head.next:
return head
new_head = self.reverseList(head.next)
head.next.next = head
head.next = None
return new_head
21、合并兩個有序鏈表
class Solution(object):
def mergeTwoLists(self, l1, l2):
head = ListNode(-1)
temp = head
while l1 and l2:
if l1.val <= l2.val:
temp.next = l1
l1 = l1.next
temp = temp.next
else:
temp.next = l2
l2 = l2.next
temp = temp.next
if l1:
temp.next = l1
if l2:
temp.next = l2
return head.next
83、刪除排序鏈表中的重復元素
class Solution(object):
def deleteDuplicates(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
if not head:
return None
else:
temp = head
cur = head.next
while cur:
if cur.val != temp.val:
temp.next = cur
temp = temp.next
cur = cur.next
temp.next = None
return head
203、移除鏈表元素
class Solution(object):
def removeElements(self, head, val):
"""
:type head: ListNode
:type val: int
:rtype: ListNode
"""
new_head = ListNode(val-1)
temp = new_head
cur = head
while cur:
if cur.val != val:
temp.next = cur
temp = temp.next
cur = cur.next
temp.next = None
return new_head.next
234、回文鏈表
第一次做的時候把值存在了列表里,然后判斷列表是不是回文列表。可以用雙指針找到中間的節(jié)點,還要用到之前的反轉(zhuǎn)鏈表,代碼比較長,也是調(diào)試了幾次才AC。
class Solution(object):
def isPalindrome(self, head):
"""
:type head: ListNode
:rtype: bool
"""
def reverseList(head):
"""
:type head: ListNode
:rtype: ListNode
"""
if not head:
return None
a, b, c = None, head, head.next
while c:
b.next = a
a, b, c = b, c, c.next
b.next = a
return b
if not head or not head.next:
return True
slow = head
fast = head
while fast.next:
if not fast.next.next:
break
else:
fast = fast.next.next
slow = slow.next
new_listnode = reverseList(slow.next)
p = new_listnode
q = head
while p:
if p.val != q.val:
return False
p = p.next
q = q.next
return True
第二次更新:2018.10.16
141、環(huán)形鏈表
使用快指針和慢指針就可以了
class Solution(object):
def hasCycle(self, head):
"""
:type head: ListNode
:rtype: bool
"""
if not head:
return False
slow = head
fast = head
while fast:
if fast.next:
fast = fast.next.next
slow = slow.next
if fast == slow:
return True
else:
return False
else:
return False
160、相交鏈表
劍指offer里面也有這題
class Solution(object):
def getIntersectionNode(self, headA, headB):
"""
:type head1, head1: ListNode
:rtype: ListNode
"""
p1 = headA
p2 = headB
while p1 != p2:
p1 = p1.next if p1.next else headB
p2 = p2.next if p2.next else headA
return p1
109、有序鏈表轉(zhuǎn)換二叉搜索樹
今天在劍指offer里刷了一道二叉搜索樹轉(zhuǎn)雙向鏈表的,這道題反過來將鏈表轉(zhuǎn)二叉搜索樹。有序鏈表的順序就是二叉搜索樹的中序遍歷的順序。
只要找到中間的節(jié)點,然后遞歸就可以了。但是鏈表找中間節(jié)點有點麻煩,可以用笨辦法先轉(zhuǎn)為列表再找中間節(jié)點,然后重新轉(zhuǎn)化為節(jié)點。但用雙指針也可以找到中間節(jié)點,不過在遞歸過程中不斷找中間節(jié)點有點困難,沒有寫出來。還是參考了別人的代碼
class Solution(object):
def sortedListToBST(self, head):
"""
:type head: ListNode
:rtype: TreeNode
"""
def convert(head, tail):
if head == tail:
return None
if head.next == tail:
return TreeNode(head.val)
fast = head
mid = head
while fast != tail and fast.next != tail:
fast = fast.next.next
mid = mid.next
root = TreeNode(mid.val)
root.left = convert(head, mid)
root.right = convert(mid.next, tail)
return root
return convert(head, None)
24、兩兩交換鏈表中的節(jié)點
直接用遞歸
class Solution(object):
def swapPairs(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
if not head:
return None
if not head.next:
return head
a, b = head, head.next
temp = self.swapPairs(b.next)
b.next = a
a.next = temp
return b
114、二叉樹轉(zhuǎn)為鏈表
要求原地修改二叉樹,所以不能先序遍歷再連接。
class Solution(object):
def flatten(self, root):
if not root:
return None
if root.left:
self.flatten(root.left)
if root.right:
self.flatten(root.right)
temp = root.right
root.right = root.left
root.left = None
while root.right:
root = root.right
root.right = temp
148、排序鏈表
題目要求了時間復雜度:O(n log n)。好像快排,歸并排序,堆排序都是O(n log n)級別的,但我還沒看,先跳過
382、鏈表隨機節(jié)點
獲得長度后用random模塊隨機一個數(shù)字代表第幾個節(jié)點
class Solution(object):
def __init__(self, head):
"""
@param head The linked list's head.
Note that the head is guaranteed to be not null, so it contains at least one node.
:type head: ListNode
"""
import random
self.head = head
def getRandom(self):
"""
Returns a random node's value.
:rtype: int
"""
if not self.head:
return None
length = 0
cur = self.head
while cur:
length += 1
cur = cur.next
index = random.randint(0, length-1)
cur = self.head
for i in range(length):
if i == index:
return cur.val
else:
cur = cur.next
i += 1
147、對鏈表進行插入排序
劍指offer刷完我就去看排序!先跳過
328、奇偶鏈表
用了三個指針。
class Solution(object):
def oddEvenList(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
if not head or not head.next:
return head
a, b, c = head, head.next, head.next.next
new_head = b
i = 0
while c:
i += 1
a.next = c
a, b, c = b, c, c.next
if i%2 == 0:
a.next = new_head
else:
b.next = new_head
a.next = None
return head
第三次更新:2018.10.17
明天要開組會,準備了一晚上組會的東西= =,抓緊時間寫兩道題
143、重排鏈表
寫了很久,想法是后半段鏈表先翻轉(zhuǎn),然后前半段和后半段交叉連接就可以了。
class Solution(object):
def reorderList(self, head):
def reverse(head):
if not head:
return None
a, b, c = None, head, head.next
while c:
b.next = a
a, b, c = b, c, c.next
b.next = a
return b
if head and head.next:
fast = head
slow = head
while fast.next:
if fast.next.next:
fast = fast.next.next
slow = slow.next
else:
break
new_head = reverse(slow.next)
a = head
b = new_head
final_head = ListNode(0)
temp = final_head
i = 0
while b:
if i%2==0:
temp.next = a
temp = temp.next
a = a.next
if i%2 == 1:
temp.next = b
temp = temp.next
b = b.next
i += 1
temp.next = a
if temp.next:
temp.next.next = None
head = temp.next
2、兩數(shù)相加
最簡單的可以直接將數(shù)值取出來再相加。當然有更好的解法,參考了別人的,用memory記錄進位
class Solution(object):
def addTwoNumbers(self, l1, l2):
mem = 0
new_head = ListNode(0)
cur = new_head
while l1 or l2:
a = l1.val if l1 else 0
b = l2.val if l2 else 0
c = a + b
if l1:
l1 = l1.next
if l2:
l2 = l2.next
cur.next = ListNode((c+mem)%10)
cur = cur.next
mem = (c+mem) // 10
if mem != 0:
cur.next = ListNode(mem)
return new_head.next
445、兩數(shù)相加Ⅱ
這題跟上一題類似,不過上一題最高位處于鏈表的尾節(jié)點,這題最高位處于頭節(jié)點。簡單一點的可以將兩個鏈表反轉(zhuǎn)后再復制上一題的代碼,但應該有更好的答案,但我沒想出來。網(wǎng)上搜了一下其實就是把值都取出來存在棧里==。看來是我想復雜了
class Solution(object):
def addTwoNumbers(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
stack1 = []
stack2 = []
while l1:
stack1.append(l1.val)
l1 = l1.next
while l2:
stack2.append(l2.val)
l2 = l2.next
answer = None
carry = 0
while stack1 and stack2:
add = stack1.pop() + stack2.pop() + carry
carry = 1 if add >= 10 else 0
temp = answer
answer = ListNode(add % 10)
answer.next = temp
l = stack1 if stack1 else stack2
while l:
add = l.pop() + carry
carry = 1 if add >= 10 else 0
temp = answer
answer = ListNode(add % 10)
answer.next = temp
if carry:
temp = answer
answer = ListNode(1)
answer.next = temp
return answer
86、分隔鏈表
用了個比較笨的辦法,用一個新鏈表存儲小于目標值的節(jié)點,另一個新鏈表存儲其它節(jié)點,最后再合并
class Solution(object):
def partition(self, head, x):
"""
:type head: ListNode
:type x: int
:rtype: ListNode
"""
smallhead = ListNode(-1)
bighead = ListNode(-1)
a , b= smallhead, bighead
cur = head
while cur:
if cur.val < x:
a.next = cur
a = a.next
cur = cur.next
else :
b.next = cur
b = b.next
cur = cur.next
a.next = None
b.next = None
cur = smallhead
while cur.next:
cur = cur.next
cur.next = bighead.next
return smallhead.next
92、反轉(zhuǎn)鏈表Ⅱ
跟反轉(zhuǎn)鏈表第一題差不多,注意一下反轉(zhuǎn)的界限就可以了。實際寫的時候出了很多問題,最終還是沒寫出來。。參考別人代碼,實際思路是一樣的
class Solution:
def reverseBetween(self, head, m, n):
"""
:type head: ListNode
:type m: int
:type n: int
:rtype: ListNode
"""
if head == None or head.next == None or m >= n or m < 0 or n < 0:
return head
h = ListNode(-1)
h.next = head
pre = h
cur = head
i = 1
while i < m and cur != None:
pre = cur
cur = cur.next
i += 1
t1 = pre
t2 = cur
while i <= n and cur != None:
lat = cur.next
cur.next = pre
pre = cur
cur = lat
i += 1
t1.next = pre
t2.next = cur
return h.next
2018.10.20
82、刪除鏈表中的重復元素Ⅱ
class Solution:
# @param head, a ListNode
# @return a ListNode
def deleteDuplicates(self, head):
if not head:
return None
new_head = ListNode(head.val - 1)
temp = new_head
a, b, c = temp, head, head.next
while b:
if not c:
if b.val != a.val:
temp.next = b
break
else:
temp.next = None
break
elif a.val != b.val != c.val:
temp.next = b
temp = b
a, b, c = b, c, c.next
else:
a, b, c = b, c, c.next
b.next = None
return new_head.next
61、旋轉(zhuǎn)鏈表
調(diào)試了很久才AC。
class Solution(object):
def rotateRight(self, head, k):
if not head:
return None
if k == 0:
return head
length = 0
cur = head
while cur:
length += 1
cur = cur.next
if length == 1 or k%length==0:
return head
pos = length - k % length + 1
cur = head
i = 1
while i < pos-1:
cur = cur.next
i += 1
temp = cur
new_head = cur.next
cur = cur.next
while cur.next:
cur = cur.next
temp.next = None
cur.next = head
return new_head
19、刪除鏈表的倒數(shù)第N個節(jié)點
遍歷兩遍鏈表的話很容易,但一遍的話沒想到該怎么做。參考別人的答案:https://blog.csdn.net/dongrongyu/article/details/78346583
想法是這樣的:維護兩個指針,pre和end。一開始初始化時使得pre指針指向鏈表頭節(jié)點,end指針指向pre+n的節(jié)點位置。然后同時往后移動pre和end指針位置,使得end指針指向最后一個節(jié)點,那么pre指針指向的則是end-n的節(jié)點位置(即倒數(shù)第n個元素的前一個節(jié)點),則將其刪除。
class Solution(object):
def removeNthFromEnd(self, head, n):
"""
:type head: ListNode
:type n: int
:rtype: ListNode
"""
if not head:
return None
fast = head
for i in range(n):
fast = fast.next
if not fast:
return head.next
slow = head
while fast.next:
fast = fast.next
slow = slow.next
slow.next = slow.next.next
return head
142、環(huán)形鏈表Ⅱ
劍指offer里刷過了
class Solution(object):
def detectCycle(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
if not head:
return None
fast = head
slow = head
while fast.next:
if not fast.next.next:
return None
else:
fast = fast.next.next
slow = slow.next
if fast == slow:
if fast==head:
return head
slow = head
while True:
fast = fast.next
slow = slow.next
if fast == slow:
return fast
return None