数据规模->时间复杂度
<=10^4 😮(n^2)
<=10^7:o(nlogn)
<=10^8:o(n)
10^8<=:o(1)
lc 941 :https://leetcode.cn/problems/valid-mountain-array/
提示:
1 <= arr.length <= 10^4
0 <= arr[i] <= 10^4
class Solution:
def validMountainArray(self, arr: List[int]) -> bool:
i=0
#升
while i<len(arr)-1 and arr[i]<arr[i+1]:i+=1
#注:边界-非单调
if i==0 or i==len(arr)-1:return False
#降
while i<len(arr)-1 and arr[i]>arr[i+1]:i+=1
#
return i==len(arr)-1
lc 189 :https://leetcode.cn/problems/rotate-array/
提示:
1 <= nums.length <= 10^5
-231 <= nums[i] <= 231 - 1
0 <= k <= 10^5
进阶:
尽可能想出更多的解决方案,至少有 三种 不同的方法可以解决这个问题。
你可以使用空间复杂度为 O(1) 的 原地 算法解决这个问题吗?
#方案一:使用额外数组(i+ k) % n
class Solution:
def rotate(self, nums: List[int], k: int) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
#o(n)
n=len(nums)
k=k%n#优化-减少移动
newarr=[0]*n
#o(n)
for i in range(n):newarr[(i+k)%n]=nums[i]
nums[:]=newarr
#
return nums
#方案二:环状替换
class Solution:
def rotate(self, nums: List[int], k: int) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
#o(1)
n=len(nums)
start=count=0#已处理元素
k=k%n
#o(n):环状交换
while count<n:
#每个环的初始
curr=start
prev=nums[start]
#交换
while True:
nums[(curr+k)%n],prev=prev, nums[(curr+k)%n]
curr=(curr+k)%n
count+=1
#边界
if curr == start:break
start+=1
return nums
#方案三:数组旋转
class Solution:
#对撞反转
def reverse(self, nums: List[int],start:int, end: int) -> None:
while start<end:
nums[start],nums[end]=nums[end],nums[start]
start+=1
end-=1
def rotate(self, nums: List[int], k: int) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
#
n=len(nums)
k=k%n
#
self.reverse(nums,0,n-1)
self.reverse(nums,0,k-1)
self.reverse(nums,k,n-1)
return nums
lc 665 :https://leetcode.cn/problems/non-decreasing-array/
提示:
n == nums.length
1 <= n <= 10^4
-10^5 <= nums[i] <= 10^5
class Solution:
def checkPossibility(self, nums: List[int]) -> bool:
#o(1)
count=0
#(n)
for i in range(1,len(nums)):
if nums[i]<nums[i-1]:
#临界
count+=1 #注:位置
if count>1:return False
#
if i>=2 and nums[i]<nums[i-2]:
nums[i]=nums[i-1]
else:nums[i-1]=nums[i]
#
return True
lc 228:提示:
0 <= nums.length <= 20
-2^31 <= nums[i] <= 2^31 - 1
nums 中的所有值都 互不相同
nums 按升序排列
class Solution:
def summaryRanges(self, nums: List[int]) -> List[str]:
#o(1)
res=[]
#o(n)
i=0
while i<len(nums):#区别于for
low=i
i+=1
while i<len(nums) and nums[i]-nums[i-1]==1:i+=1
high=i-1
#
tmp=str(nums[low])
if low<high:
tmp+="->"
tmp+=str(nums[high])
#
res.append(tmp)
#
return res
lc 163 :https://leetcode.cn/problems/missing-ranges/
class Solution:
def findMissingRanges(self, nums: List[int], lower: int, upper: int) -> List[str]:
#o(1)
res=[]
#o(n)
pre=lower-1
nums.append(upper+1)
for num in nums:
if num-pre==2:res.append(str(pre+1))
if num-pre>2:res.append(str(pre+1)+'->'+str(num-1))
pre=num
#
return res
lc 31【top100】:https://leetcode.cn/problems/next-permutation/
提示:
1 <= nums.length <= 100
0 <= nums[i] <= 100
必须 原地 修改,只允许使用额外常数空间
#找到尽量靠右的【较小数】;找到尽量靠右且比【较小数】大的【较大数】
class Solution:
def nextPermutation(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
#o(n)
#【较小数】
i=len(nums)-2#注:起始点
while i>=0 and nums[i]>=nums[i+1]:i-=1
#【较大数】
if i>=0:
j=len(nums)-1
while nums[j]<=nums[i]:j-=1 #注:<=,>=
#o(1)
#交换
nums[i],nums[j]=nums[j],nums[i]
#o(n)反序
left,right=i+1,len(nums)-1
while left<right:
nums[left],nums[right]=nums[right],nums[left]
left+=1
right-=1
#
return nums
lc 135:https://leetcode.cn/problems/candy/
提示:
n == ratings.length
1 <= n <= 2 * 10^4
0 <= ratings[i] <= 2 * 10^4
#方案一:暴力解法(超时)
class Solution:
def candy(self, ratings: List[int]) -> int:
#o(n)
n=len(ratings)
candies=[1]*n
#o(n^2)
haschange=True
while haschange:
haschange=False
#
for i in range(n):
if i<n-1 and ratings[i]>ratings[i+1] and candies[i]<=candies[i+1]:
candies[i]=candies[i+1]+1
haschange=True
if i>0 and ratings[i]>ratings[i-1] and candies[i]<=candies[i-1]:
candies[i]=candies[i-1]+1
haschange=True
#
return sum(candies)
#方案二:'两个数组'(优化-其中一个数组可用变量代替)加上两次遍历
class Solution:
def candy(self, ratings: List[int]) -> int:
#o(n)
n=len(ratings)
left2right=[1]*n
right2left=1 #变量形式
sm=0
#o(n)
for i in range(n):
if i>0 and ratings[i]>ratings[i-1]:
left2right[i]= left2right[i-1]+1
for i in range(n-1,-1,-1):
if i<n-1 and ratings[i]>ratings[i+1]:
right2left +=1
else:right2left =1
sm +=max(left2right[i],right2left)
#
return sm
lc 605 :https://leetcode.cn/problems/can-place-flowers/
提示:
1 <= flowerbed.length <= 2 * 104
flowerbed[i] 为 0 或 1
flowerbed 中不存在相邻的两朵花
0 <= n <= flowerbed.length
#1-0-0-0-1-0-0-0-1
class Solution:
def canPlaceFlowers(self, flowerbed: List[int], n: int) -> bool:
#
w=len(flowerbed)
#
i=0
while i<w and n>0:
if flowerbed[i]==1:
i+=2
elif i==w-1 or flowerbed[i+1]==0: #1-0-0,1-0-0-0
n-=1
i+=2
else:i+=3#0-1-0-0
#
return n==0
lc 860 :https://leetcode.cn/problems/lemonade-change/
提示:
1 <= bills.length <= 105
bills[i] 不是 5 就是 10 或是 20
class Solution:
def lemonadeChange(self, bills: List[int]) -> bool:
#
five=ten=0
#
for bill in bills:
if bill==5:
five+=1
elif bill==10:
if five==0:return False #注
five-=1
ten+=1
else:
if five>0 and ten>0:
#注
five-=1
ten-=1
elif five>=3:
#注
five-=3
else: return False
#
return True