第二章 链表part01
day1 任务以及具体安排:第一章 数组part01
day 2 任务以及具体安排:第一章 数组part02
203.移除链表元素
题目链接/文章讲解/视频讲解::代码随想录
如何移除元素:第一步是找到他的上一个元素,然后将这个元素的next属性变成current.next.next,也就是跳过我们要删除的元素。
这里用到一个技巧,即虚拟头结点。
这样就可以用 某某.next表示所有元素,包括第一个元素。
返回的时候注意 去掉虚拟头即可
def removeElements(head, val): fix_head = ListNode(next=head) current = fix_head while current.next: if current.next.val == val: current.next = current.next.next else: current = current.next return fix_head.next
707.设计链表
题目链接/文章讲解/视频讲解:代码随想录
生成链表的时候要注意,链表head用虚拟头结点表示,以及初始化链表的size,方便检测之后带有index操作的函数是否符合规范。
class Node: def __init__(self, val = 0, next = None) -> None: self.val = val self.next = next class MyLinkedList: def __init__(self): self.head = Node() self.size = 0 def get(self, index: int) -> int: if index < 0 or index > self.size - 1: return -1 current_head = self.head current_index = 0 while current_head.next and current_index < index: current_head = current_head.next current_index += 1 print(f'current cal = {current_head.next.val}') return current_head.next.val def addAtHead(self, val: int) -> None: current = Node(val) current.next = self.head.next self.head.next = current self.size += 1 def addAtTail(self, val: int) -> None: current = Node(val) current_head = self.head while current_head.next: current_head = current_head.next current_head.next = current self.size += 1 def addAtIndex(self, index: int, val: int) -> None: if index < 0 or index > self.size: return current = Node(val) current_head = self.head current_index = 0 while current_head.next and current_index < index: current_head = current_head.next current_index += 1 current.next = current_head.next current_head.next = current self.size += 1 def deleteAtIndex(self, index: int) -> None: if index < 0 or index > self.size - 1: return current_head = self.head # print(self.head.__dict__) # print(current_head.__dict__) # print(current_head == self.head) current_index = 0 while current_head.next and current_index < index: current_head = current_head.next current_index += 1 current_head.next = current_head.next.next self.size -= 1 def print_lst(self): current = self.head while current.next: print(current.val) current = current.next print(current.val)
206.反转链表
题目链接/文章讲解/视频讲解:
反转链表【基础算法精讲 06】_哔哩哔哩_bilibili (点击接受灵茶山大神的启迪)
拿到这道题我的第一想法就是递归:
# 思路1: 递归 class Solution: def reverseList(self, head): if not head: return part1 = head if part1.next == None: return part1 if part1.next.next != None: part2 = part1.next part2 = self.reverseList(part2) else: part2 = part1.next # part2 = reverseList(part2) # part1.next, part2.next = None, part1 part1.next = None current_head = part2 while current_head.next: current_head = current_head.next current_head.next = part1 # head = part2 return part2
套娃方法对于空表与只有一个元素的情况下浪费了不少时间。但是我觉得这个思路也是不错的。
即先将最开头那个取出,将next重置为none,之后对于part2部分也做相同的事情,最后交换位置。可以先看懂量个元素的交换流程。
例子:
1 2 3 4
1 2 3 4
1 2 3 4 分割到两个元素结束
1 2 43
1 432
4321
遍历方式其实思路也很简单:
将 None 1 -> 2 -> 3 -> None
变成 None <- 1 <- 2 <- 3 None
然而这样看起来简单的操作需要用到3个指针, 我们把操作部分称为part1, 待操作部分称为part2,同时用part2指针指向2。
此时current指针指向我们现在操作的元素,也就是1。. part1中将1本来指向2的next重置为他的上一个元素,也就是与None相连接。
此时part1部分的工作已经完成,我们将current指针移向下一个要操作的部分2
不难看出 part1代表已经转换完成的部分,同时也是下一步中current要指向的地方,当current为None时,循环结束
#思路2 遍历 class Solution: def reverseList(self, head): part1 = None current = head part2 = None while current: part2 = current.next current.next = part1 part1 = current current = part2 return part1
第二章 链表part02
24. 两两交换链表中的节点
用虚拟头结点,这样会方便很多。
def swapPairs(head): fixhead = ListNode(0, head) current = fixhead # index = 0 while current.next: if current.next.next == None: break else: part1 = current.next part2 = current.next.next #1.next = 2.next part1.next= part2.next #2.next = 1 part2.next = part1 current.next = part2 current = current.next.next return fixhead.next
19.删除链表的倒数第N个节点
双指针的操作,要注意,删除第N个节点,那么我们当前遍历的指针一定要指向 第N个节点的前一个节点,建议先看视频。
#更好的方法,右指针先走n步,再左右指针一起走 def removeNthFromEnd(head, n): fixhead= ListNode(next=head) right = fixhead for _ in range(n): right = right.next left = fixhead while right.next: right = right.next left = left.next left.next = left.next.next return fixhead.next
面试题 02.07. 链表相交
本题没有视频讲解,大家注意 数值相同,不代表指针相同。
题目链接/文章讲解:代码随想录
142.环形链表II
算是链表比较有难度的题目,需要多花点时间理解 确定环和找环入口,建议先看视频。
题目链接/文章讲解/视频讲解:代码随想录
老老实实看解释吧,我是菜逼。这题难点在确认是环后找到入口 x = z 悟到这个才算明白。
class Solution: def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]: fast = head slow = head while fast and fast.next: fast = fast.next.next slow = slow.next if fast is slow: #判断id(fast) == id(slow) 引用相同则表示重叠 start = head while start is not slow: start = start.next slow = slow.next return slow return None