一、今日任务
二、 两两交换链表中的节点
2.1 题目:24. 两两交换链表中的节点
2.2 解题过程
简单的模拟题目。
遇到的问题是交换之后head.next没有更新导致失去了部分节点,这也是提示用虚拟头结点的原因。
代码如下
class Solution(object):
# 简单模拟 虚拟头结点非常重要。以及NULL or 1 个节点的链表要单独讨论
def swapPairs(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
NewHead = ListNode()
NewHead.next = head
if head == None or head.next == None:
return head
else:
ppre = NewHead ##important
pre = head
cur = head.next
while cur != None:
temp = cur.next
cur.next = pre
pre.next = temp
ppre.next = cur ## important
if temp == None or temp.next == None:
break
else:
ppre = pre ## important
pre = temp
cur = temp.next
return NewHead.next
毫不意外,超时。
也看到了建议在O(n)的时间复杂度里解出来。
其实可以看做一个非有序的数组进行排序。只要找到O(n)的排序方法就行。
这是想到了归并排序。只要找到分段处就可以执行。
代码如下:
def sortedSquares1(self, nums):
"""
:type nums: List[int]
:rtype: List[int]
"""
NewNums = []
flag = -1
for i in range(0, len(nums)):
if nums[i] < 0:
flag = i
nums[i] = nums[i] * nums[i]
if flag == -1:
return nums
else:
n = flag
p = flag + 1
i = 0
while n >= 0 and p < len(nums):
if nums[n] < nums[p]:
NewNums.append(nums[n])
n -= 1
else:
NewNums.append(nums[p])
p += 1
i += 1
while i < len(nums) and n >= 0:
NewNums.append(nums[n])
n -= 1
i += 1
while i < len(nums) and p < len(nums):
NewNums.append(nums[p])
p += 1
i += 1
return NewNums
2.3 阅读材料改进
文章中的代码显得简洁很多。但思路大体一致。
以下是复现代码:
# 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
"""
NewHead = ListNode(next = head)
cur = NewHead
while cur.next and cur.next.next:
pre = cur
cur = cur.next
post = cur.next
temp = cur.next.next
pre.next = post
post.next = cur
cur.next = temp
cur = pre.next.next
return NewHead.next
三、删除链表的倒数第 N 个结点
3.1 题目:19. 删除链表的倒数第 N 个结点
3.2 解题过程
拿到这一题,第一反应就是要第一遍遍历计算链表长度,第二遍遍历定位删除。遇到一个问题,每次都想要直接返回head,但是忘记head节点不一定是头结点了。
class Solution(object):
def removeNthFromEnd(self, head, n):
"""
:type head: ListNode
:type n: int
:rtype: ListNode
"""
newheadFsize = ListNode(next = head)
newheadFdelete = ListNode(next=head)
NewHead =newheadFdelete
size = 0
while newheadFsize.next:
size += 1
newheadFsize = newheadFsize.next
index = size - n
while newheadFdelete.next:
if index == 0:
newheadFdelete.next = newheadFdelete.next.next
break
index -= 1
newheadFdelete = newheadFdelete.next
return NewHead.next
按照随想录的进阶要求是在一次遍历上解决这个问题。
主要难点是在定位,这时候想到的是快慢指针的方法。希望能够有用。结果是成功啦。
# 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
"""
newheadFdelete = ListNode(next=head)
NewHead =newheadFdelete
prev = NewHead
post = NewHead
while post.next:
if n:
post = post.next
n -= 1
else:
post = post.next
prev = prev.next
prev.next = prev.next.next
return newheadFdelete.next
3.3 阅读材料改进
第二个版本的代码与随想录里思路一致。开心!
显然会比一个while,彻底解决自己得一个很大的问题。
四 、面试题 02.07. 链表相交
4.1 题目:面试题 02.07. 链表相交
4.2 解题过程
看第一遍题目的时候还是有点茫然,有点不知所措。
老规矩,先暴力解,再考虑优化问题。果不其然超时41/45
# 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
"""
NewHeadA = ListNode(next = headA)
NewHeadB = ListNode(next = headB)
A = NewHeadA
B = NewHeadB
while A.next:
while B.next:
if A.next == B.next:
return A.next
B = B.next
B = NewHeadB
A = A.next
return None
时间复杂度要求O(n),那么就一定是要只有一边遍历,验证节点相同的条件就是 A==B。这时想到的是分别反转链表,再同时反转遍历。这样时间复杂度就为O(n+m+x)
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def ListReverse(self, head):
Newhead = ListNode(next = head)
newhead = ListNode(next = head)
prev = newhead.next
post = newhead.next.next
while post:
temp = post.next
post.next = newhead.next
prev.next = temp
newhead.next = post
post = temp
return newhead
def getIntersectionNode(self, headA, headB):
"""
:type head1, head1: ListNode
:rtype: ListNode
"""
RA = self.ListReverse(headA)
RB = self.ListReverse(headB)
while RA.next and RB.next:
if RA.next == RB.next:
return RA.next
RA = RA.next
RB = RB.next
return None
千辛万苦做好,发现不允许修改链表结构。
灰心丧气去看了解答。
4.3 阅读材料改进
很简单的算法呀,怎么就没想到!!找到较长的链表,将其指针移到和短链表同一起点,一一对应比较!
class Solution(object):
def getIntersectionNode(self, headA, headB):
"""
:type head1, head1: ListNode
:rtype: ListNode
"""
NewHeadA = ListNode(next=headA)
NewHeadB = ListNode(next=headB)
headFsizeA = NewHeadA
headFsizeB = NewHeadB
lengthA = 0
lengthB = 0
while headFsizeA.next:
headFsizeA = headFsizeA.next
lengthA += 1
while headFsizeB.next:
headFsizeB = headFsizeB.next
lengthB += 1
if lengthA > lengthB:
longer = lengthA
shorter = lengthB
shorterhead = NewHeadB
longerhead = NewHeadA
else:
longer = lengthB
shorter = lengthA
shorterhead = NewHeadA
longerhead = NewHeadB
discrepancy = longer - shorter
while discrepancy:
longerhead = longerhead.next
discrepancy -= 1
while longerhead.next:
if longerhead.next == shorterhead.next:
return longerhead.next
longerhead = longerhead.next
shorterhead = shorterhead.next
return None
五、142. 环形链表II
5.1 题目:142. 环形链表 II
5.2 解题过程
目前来说,最简单暴力的方法就是遍历存储,出现第一个相等的结点就是。
暴力解法如下:
class Solution(object):
def detectCycle(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
newhead = ListNode(next = head)
cur = newhead
nodelist = []
while cur.next:
for i in nodelist:
if i == cur.next:
return i
nodelist.append(cur.next)
cur = cur.next
return None
力扣进阶要求是使用O(1)的空间复杂度。遍历一圈,寻找哪两个next相等。这个方法显然不行,因为根本没有条件遍历,是一个环只会无穷循环。实在想不出。看随想录吧。
5.3 阅读材料改进
思考方向一定是快慢指针,但是没想到其中的涉及到能够相遇。
思路是,先判断有环,再判断入口。
理论知识有点混乱,今天就先不复现了。
class Solution:
def detectCycle(self, head: ListNode) -> ListNode:
slow, fast = head, head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
# 如果相遇
if slow == fast:
p = head
q = slow
while p!=q:
p = p.next
q = q.next
#你也可以return q
return p
return None