LeetCode 24. 两两交换链表中的节点
需要注意的地方:
- cur(操作的指针)必须指向一对需要交换的节点的前一个节点,因为不仅要改变两个节点内部的指向,还要改变前一个节点与这两个节点的指向
- 是通过更改节点的指向来更改节点的位置,(因为链表在内存空间中不是连续分布的,是散乱的分布在内存中,通过指针将各个位置的节点连接成链表)所以不能通过赋值来让节点相等

- 循环结束条件:奇数个元素(cur.next.next=None)偶数个元素(cur.next=None)
- cur指向需交换的两个节点的上一个节点,所以cur每次向后移两位
- 注意交换两个节点需要三步,举例:第一步,让dummyhead指向2,第二步,让2指向1,第三步,让1指向3,第三步容易遗忘
- 在改变节点的指向之前,一定要记得先用临时指针temp去保存节点原来的指向,不然在改变指向之后就找不到原来的节点了
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution(object):
def swapPairs(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
dummyhead = ListNode()
dummyhead.next = head
cur = dummyhead # 才能对最开始的两个节点进行操作
while cur.next != None and cur.next.next != None:
temp = cur.next # 在dummyhead指向2之前将节点1保存,不然就找不到1了
cur.next = cur.next.next # step1:让dummyhead指向2,此时2已经成为cur.next
temp1 = cur.next.next # 在2指向1之前将节点3保存,不然就找不到3了
cur.next.next = temp # step2:让2指向1(同时2和3之间的连接就断了)
temp.next = temp1 # step3:让1指向3
cur = cur.next.next # cur向后移两位
return dummyhead.next
19. 删除链表的倒数第 N 个结点
注意:
- 提供给你的参数只有头结点head和n(倒数第n个),所以你是不知道链表的长度的,除非先将链表遍历一遍去获得链表的长度L,并将L-n+1作为你需要删除的索引,然后再从头开始用while循环然后index–去找到index的上一个节点
- 双指针法:一个快指针和一个慢指针,让快指针先走n步,然后慢指针再开始走,快慢指针速度相同,当快指针走到尾结点的时候,慢指针正好走到倒数第N个节点的前一个节点,通过慢指针将倒数第N个节点删除即可
- 使用虚拟头结点主要是因为不需要对操作节点是不是头结点进行一个特殊的判断,而可以采用统一的一个方式进行删除
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution(object):
def removeNthFromEnd(self, head, n):
"""
:type head: ListNode
:type n: int
:rtype: ListNode
"""
dummyhead = ListNode()
dummyhead.next = head
fast = dummyhead
slow = dummyhead
while fast.next != None:
fast = fast.next
if n > 0:
n -= 1
else:
slow = slow.next
slow.next = slow.next.next
return dummyhead.next
面试题 02.07. 链表相交
注意:
- 本题的难点在于链表A,B的长度不同,若两个链表长度相同,则让两个cur分别从两个链表的头结点出发,若相等,则找到交点。但由于长度不同,就不知道两个cur该如何同步了
- 所以应该分别求出链表A,B的长度及长度的差值n,让长的那一条链表的指针先走n步,(这样剩下的链表长度就相等了)然后再让两个指针同时移动,若相等,则找到交点
- 为了方便,总是让curA为更长链表的头
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def getIntersectionNode(self, headA, headB):
"""
:type head1, head1: ListNode
:rtype: ListNode
"""
cur1 = headA
l1 = 0
while cur1 != None: # 求链表A的长度
cur1 = cur1.next
l1 += 1
cur2 = headB
l2 = 0
while cur2 != None: # 求链表B的长度
cur2 = cur2.next
l2 += 1
cur1 = headA
cur2 = headB
# 求链表的长度差
if l1 >= l2:
n = l1-l2
else:
n = l2-l1
cur1, cur2 = cur2, cur1
# 总是让cur1为更长链表的头 方便后续的操作
# 让cur1和cur2在同一起点上(末尾位置对齐)
while n > 0 and cur1 != None:
cur1 = cur1.next
n -= 1
# 让cur1和cur2同时移动,若相同则找到交点并返回
while cur1 != None and cur2 != None:
if cur1 == cur2:
return cur1
else:
cur1 = cur1.next
cur2 = cur2.next
return None # 若链表遍历结束还未找到,则没有交点,返回空值
142. 环形链表 II
注意:
- 快指针一次走两个节点,慢指针一次走一个节点,如果链表有环,则快慢指针一定会在环内相遇。why?因为一定是快指针先入环,然后慢指针入环,在环内,其实是快指针追慢指针的一个过程。快指针相对于慢指针以一次移动一个节点的速度去靠近慢指针,所以他俩一定会相遇(快指针不会跳过去)
- 由快指针的速度是慢指针的两倍,经过同样的时间,快指针走过的路程是慢指针的两倍,可以得到一个等式,x+n(y+z)+y=2(x+y),n是快指针在环里转了n圈才遇到慢指针。对等式进行化简,可以发现:x=z(当n=1时),x=z+n(y+z)(其他),于是令一个指针index1指向头结点,一个指针index2指向快慢指针相遇的节点,然后让这两个指针同时移动,他们相遇的地方就是环的入口。如果n>1,就是index2在环内转了n-1圈才会遇上index1。 但总之,他们相遇的节点就是环的入口。
- 慢指针在转第一圈的时候就一定会被快指针给追上,因为慢指针转一圈,快指针能转两圈,所以快指针一定会经过慢指针。
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def detectCycle(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
fast = head
slow = head
while fast != None and fast.next != None: # 注意要判断fast.next != None 因为fast一次走两步
fast = fast.next.next
slow = slow.next
if fast == slow: # 快慢指针相遇,链表有环
index1 = head
index2 = fast
while index1 != index2:
index1 = index1.next
index2 = index2.next
return index1
return None

1875




被折叠的 条评论
为什么被折叠?



