24 两两交换链表的节点
力扣
思路:
还是看了carl哥的视频讲解才写出来。有点难搞
首先 还是老样子 需要一个dummyhead虚拟头节点。
然后核心就是 我们要操作后面两个节点的时候 一定要移动到 这两个节点的上一个节点。
(来自代码随想录)
然后返回我们的虚拟节点.next即可
def swapPairs(self, head: Optional[ListNode]) -> Optional[ListNode]:
dummy_head = ListNode(0)
dummy_head.next = head
cur = dummy_head
while cur.next!=None and cur.next.next!=None:
temp = cur.next
temp1 = cur.next.next.next
cur.next = cur.next.next
cur.next.next = temp
temp.next = temp1
cur = cur.next.next
return dummy_head.next
19 删除倒数第n个节点
力扣
思路:
这道题 理解一下 倒数第n个。我认为按照我这么理解更好,倒数第n个就说明当前后半部分有多少个元素。举个例子[1,2,3,4,5].比如说n=2,那就是倒数第二个,是不是最后只有2和5这两个元素了。那么我们可不可以先计算出 一共有多少个元素。然后用一个count记录总个数,再减去这个n。是不是就刚好是前面有多少元素。然后设置一个指针在range(count-n)中走这么多步
然后会惊奇的发现 走了这么多步数以后当前的cur指针 刚好是倒数第n个节点的上一个节点。
这个时候只需要让cur的next指针指向下下个元素 就完成了删除节点的操作了!
代码:
def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
count = 0
dummy_head = ListNode(None,next = head)
cur = dummy_head
#设置快指针
fast = dummy_head
while cur.next!=None:
cur = cur.next
count+=1
steps = count
for _ in range(steps-n):
fast = fast.next
fast.next = fast.next.next
return dummy_head.next
16-相交链表
力扣
思路:
这道题依靠自己写了绝大部分 但是最核心的交换两个链表 的步骤还是看了以前写的笔记。。
核心就是:值相同 不代表指针相同
首先 是计算ab链表的长度,并且计算他们的差值。
然后 让长度短的链表 移动到 和长的链表末尾对齐的位置
再去进行比较
最后判断 return headA if headA==headB else none
代码:
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> Optional[ListNode]:
cur = headA
len_a = 0
len_b = 0
cur_b = headB
while cur.next:
cur = cur.next
len_a+=1
step_a = len_a
while cur_b.next:
cur_b = cur_b.next
len_b+=1
step_b = len_b
cur = headA
cur_b = headB
if step_b > step_a:
step_a,step_b = step_b,step_a
cur,cur_b = headB,headA
gap = abs(step_a-step_b)
while gap!=0:
cur = cur.next
gap-=1
while cur!=None:
if cur==cur_b:
return cur
cur = cur.next
cur_b = cur_b.next
return None
环形链表
142力扣
这道题,我没有想到 找到了环之后 还要再一次找入口 这是我的读题问题 没有理解到
我以为只要是找到了环可以直接返回
思路:
这道题 可能会用到一个数学推理
这里用一下卡哥的笔记 (来自代码随想录)
如何判断有没有环:一开始分别设置快慢指针 快指针走两步 慢的走一步。如果他们两个相遇 肯定是在环内相遇 因为快指针肯定比慢的要先进入环中。所以他们的第一次相遇肯定是在环内。
判断了有环之后:慢指针走过的节点数是x+y
快指针走过的节点数是x+y+n(y+z) n代表快指针在里面走了几圈。因为快指针最少也要一圈才能重新追上慢指针。并且 快指针一次走两步
所以 在快指针走的节点数的基础上还要*2
所以当2*(x+y) = x+y+n(y+z)
解开之后x +y = n(y+z).既然是找环的入口 ,那肯定是出现在x上面,要求的就是x
x = ny+nz-y
提一个y出来,x = y(n-1)+nz
我们明确了n是>=0的。所以当n = 1的时候,x = z。所以从头结点出发一个指针,从相遇节点 也出发一个指针,这两个指针每次只走一个节点, 那么当这两个指针相遇的时候就是 环形入口的节点。(来自随想录)
代码:
def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]:
#设置快慢指针
fast = head
slow = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow==fast:
slow = head
while slow!=fast:
slow = slow.next
fast = fast.next
return slow
return None