581. 最短无序连续子数组
排序后比较两个数组最左边和最右边不一致的元素
超时
class Solution:
def findUnsortedSubarray(self, nums: List[int]) -> int:
l,r=len(nums),0
for i in range(len(nums)-1):
for j in range(i,len(nums)):
if nums[i]>nums[j]:
l=min(l,i)
r=max(r,j)
return r-l+1 if r-l+1>0 else 0
使用两次栈
class Solution:
def findUnsortedSubarray(self, nums: List[int]) -> int:
stack=[]
r=float('-inf')
l=float('inf')
#单调递增栈,找到最左边的边界
for i in range(len(nums)):
while stack and nums[i]<nums[stack[-1]]:
l=min(l,stack.pop())
stack.append(i)
stack=[]
#从后往前构造单调递减栈,找到最右边的边界
for i in range(len(nums)-1,-1,-1):
while stack and nums[i]>nums[stack[-1]]:
r=max(stack.pop(),r)
stack.append(i)
return r-l+1 if r-l>0 else 0
链表
快慢指针,用于定位节点
巧用dummpy,在头结点发生改变时,不需要考虑头结点的特殊处理,只要返回dummpy->next作为头结点即可
160. 相交链表
class Solution:
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
pre1,pre2=headA,headB
while pre1!=pre2 :
pre1=pre1.next if pre1 else headB
pre2=pre2.next if pre2 else headA
return pre1
重排链表:需要用到分治和 递归
143. 重排链表
class Solution:
def reverseList(self, head):
pre = None
cur = head
while cur:
tmp=cur.next
cur.next=pre
pre=cur
cur=tmp
return pre
def reorderList(self, head: ListNode) -> None:
"""
Do not return anything, modify head in-place instead.
"""
if not head:
return head
slow, fast = head, head
#快慢指针分为前后两端
while fast and fast.next:
slow, fast = slow.next, fast.next.next
p = slow.next
slow.next = None
#翻转后半段链表
p = self.reverseList(p)
m = head
while p:
#将后半段链表接到前半段
m.next,p.next,m,p=p,m.next,m.next,p.next
return head
61. 旋转链表
先将链表闭合成环,在合适的地方断开
class Solution:
def rotateRight(self, head: ListNode, k: int) -> ListNode:
if not head:
return
if not head.next:
return head
count=1
#原链表闭合成环
old_tail=head
while old_tail.next:
old_tail=old_tail.next
count+=1
old_tail.next=head
#找到新的断开点
m=count-k%count-1
new_tail=head
for i in range(m):
new_tail=new_tail.next
head=new_tail.next
new_tail.next=None
return head
707. 设计链表
单向链表
class listnode:
def __init__(self,val):
self.val=val
self.next=None
class MyLinkedList:
def __init__(self):
"""
Initialize your data structure here.
"""
self.head=listnode(0)
self.size=0
def get(self, index: int) -> int:
"""
Get the value of the index-th node in the linked list. If the index is invalid, return -1.
"""
if index<0 or index>=self.size:
return -1
cur=self.head
for _ in range(index+1):
cur=cur.next
return cur.val
def addAtHead(self, val: int) -> None:
"""
Add a node of value val before the first element of the linked list. After the insertion, the new node will be the first node of the linked list.
"""
return self.addAtIndex(0,val)
def addAtTail(self, val: int) -> None:
"""
Append a node of value val to the last element of the linked list.
"""
return self.addAtIndex(self.size,val)
def addAtIndex(self, index: int, val: int) -> None:
"""
Add a node of value val before the index-th node in the linked list. If index equals to the length of linked list, the node will be appended to the end of linked list. If index is greater than the length, the node will not be inserted.
"""
if index>self.size:
return
if index<0:
index=0
self.size+=1
pre=self.head
for _ in range(index):
pre=pre.next
newnode=listnode(val)
newnode.next=pre.next
pre.next=newnode
def deleteAtIndex(self, index: int) -> None:
"""
Delete the index-th node in the linked list, if the index is valid.
"""
if index<0 or index>=self.size:
return
self.size-=1
pre=self.head
for _ in range(index):
pre=pre.next
pre.next=pre.next.next
817. 链表组件
class Solution:
def numComponents(self, head: ListNode, G: List[int]) -> int:
count=0
cur=head
stack=[]
#直接用列表G很慢,换成set(G)就很快
G=set(G)
while cur:
if cur.val in G:
stack.append(cur.val)
else:
if stack:
count+=1
stack=[]
cur=cur.next
if stack:
count+=1
return count
189 旋转数组
原地算法:python的切片实现开销了额外空间。O(N)的复杂度
class Solution:
def rotate(self, nums: List[int], k: int) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
n=len(nums)
m=n-k%n
nums[m:],nums[:m]=nums[:m],nums[m:]
旋转算法:
先选数组第一项,找到它应该存放的位置。接着选中这个位置上的数,移动到它适合的位置,需要记录已经处理过的序号,遇到死循环的,变为处理下一项
每一次将idx的数据放置到target的位置上,同时将target的位置上的数据存到tmp中
tmp存储下一个应该变动的数据,即这个位置上的数,tmp是一个临时位置
例如 nums=[1,2,3,4],k=2,第一次1挪到3的位置,tmp=3,第二次将3挪到1的位置,此时Target=0已经处理过了,接着处理下一项,即index=target+1,tmp=nums[target+1]
class Solution:
def rotate(self, nums: List[int], k: int) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
n=len(nums)
count=0
idx,tmp=0,nums[0]
hash=[0]
while count<n:
#计算tmp应该挪到的位置target
count,target=count+1,(idx+k)%n
tmp,nums[target]=nums[target],tmp
if target not in hash :
idx=target
elif target+1<n:
idx=target+1
tmp=nums[idx]
hash.append(idx)
328. 奇偶链表
class Solution:
def oddEvenList(self, head: ListNode) -> ListNode:
if not head:
return head
h1,h2=head,head.next
slow,fast=head,head.next
while fast and fast.next:
slow.next=slow.next.next
fast.next=fast.next.next
slow=slow.next
fast=fast.next
slow.next=h2
return head
725. 分隔链表
class Solution:
def splitListToParts(self, root: ListNode, k: int) -> List[ListNode]:
count=0
s1=root
while s1:
count+=1
s1=s1.next
#m个链表应该多1
m=count%k
#每个链表的长度
n=count//k
ans=[]
cur=root
for i in range(k):
#每一段的头结点
head=cur
#找到分割点断开
for j in range(n+(1 if i<m else 0)-1):
if cur:
cur=cur.next
if cur:
cur.next,cur=None,cur.next
ans.append(head)
return ans
面试题18. 删除链表的节点
class Solution:
def deleteNode(self, head: ListNode, val: int) -> ListNode:
dummy=ListNode(0)
dummy.next=head
cur=dummy
while cur.next.val!=val:
cur=cur.next
cur.next=cur.next.next
return dummy.next