数据规模->时间复杂度
<=10^4 😮(n^2)
<=10^7:o(nlogn)
<=10^8:o(n)
10^8<=:o(logn),o(1)
内容
lc 455 :分发饼干 - 贪心思想
https://leetcode.cn/problems/assign-cookies/
提示:
1 <= g.length <= 3 * 10^4
0 <= s.length <= 3 * 10^4
1 <= g[i], s[j] <= 231 - 1
class Solution:
def findContentChildren(self, g: List[int], s: List[int]) -> int:
#o(nlogn)
s.sort()
g.sort()
#
i=j=0
while i<len(s) and j<len(g):
if s[i]>=g[j]:
j+=1
i+=1
return j
lc 322 【剑指 103】【top100】:零钱兑换 - 贪心 + 回溯
https://leetcode.cn/problems/coin-change/
提示:
1 <= coins.length <= 12
1 <= coins[i] <= 2^31 - 1
0 <= amount <= 10^4
#方案一:贪心失效->回溯(超时)
class Solution:
def coinChange(self, coins: List[int], amount: int) -> int:
self.min_num=float('inf')
self.dfs(coins,amount,[])
#
return self.min_num if self.min_num!=float('inf') else -1
def dfs(self,coins,amount,path):
#if amount<0:return
if amount==0:
self.min_num=min(self.min_num,len(path[:]))
return
#
for i in range(len(coins)):
if amount-coins[i]<0:continue
path.append(coins[i])
self.dfs(coins,amount-coins[i],path)
path.pop()
#方案二:回溯+贪心(超时)(不能提升性能)
#方案三:动态规划
贪心算法的特点
lc 45 :跳跃游戏 Ⅱ
https://leetcode.cn/problems/jump-game-ii/
提示:
1 <= nums.length <= 10^4
0 <= nums[i] <= 1000
class Solution:
def jump(self, nums: List[int]) -> int:
if len(nums)==1:return 0
#写法1
steps=0
start=end=0
while end<len(nums)-1:
max_pos=0
for i in range(start,end+1):
max_pos=max(max_pos,i+nums[i])
#key:更新
start=end+1
end=max_pos
steps+=1
return steps
# #写法2
# steps=0
# end=0
# max_pos=0
# for i in range(len(nums)-1):
# max_pos=max(max_pos,i+nums[i])
# #key:更新
# if i==end:
# end=max_pos
# steps+=1
# return steps
lc 55 :跳跃游戏【top100】
https://leetcode.cn/problems/jump-game/
提示:
1 <= nums.length <= 3 * 10^4
0 <= nums[i] <= 10^5
class Solution:
def canJump(self, nums: List[int]) -> bool:
max_pos=0
for i in range(len(nums)):
if max_pos<i:return False
max_pos=max(max_pos,i+nums[i])
return True
lc 1578 :避免重复字母的最小删除成本
https://leetcode.cn/problems/minimum-time-to-make-rope-colorful/
提示:
n == colors.length == neededTime.length
1 <= n <= 10^5
1 <= neededTime[i] <= 10^4
colors 仅由小写英文字母组成
class Solution:
def minCost(self, colors: str, neededTime: List[int]) -> int:
min_cost=0
i=0
while i<len(colors): #key:while
max_cost=sum_cost=0
#
curr_color=colors[i]
while i<len(colors) and colors[i]==curr_color:
max_cost=max(max_cost,neededTime[i])
sum_cost+=neededTime[i]
i+=1
#
min_cost+=sum_cost-max_cost
return min_cost
lc 402 :移掉K位数字
https://leetcode.cn/problems/remove-k-digits/
提示:
1 <= k <= num.length <= 105
num 仅由若干位数字(0 - 9)组成
除了 0 本身之外,num 不含任何前导零
#贪心+双端队列
class Solution:
def removeKdigits(self, num: str, k: int) -> str:
queue=deque()
#
for c in num:
#key
while queue and queue[-1]>c and k>0:
queue.pop()
k-=1
queue.append(c)
for i in range(k):
queue.pop()
#
res=''
is_first=True
while queue:
curr=queue.popleft()
if curr=='0' and is_first:continue
is_first=False
res +=curr
return res if len(res)!=0 else '0'
lc 409 :最长回文串
https://leetcode.cn/problems/longest-palindrome/
提示:
1 <= s.length <= 2000
s 只由小写 和/或 大写英文字母组成
class Solution:
def longestPalindrome(self, s: str) -> int:
cnt=[0]*128
#
for c in s:
cnt[ord(c)]+=1
#key
res=0
for v in cnt:
res+=(v//2)*2
if res%2==0 and v%2==1: #aaa
res+=1
return res
lc 680【剑指 019】:验证回文字符串 Ⅱ
https://leetcode.cn/problems/valid-palindrome-ii/
提示:
1 <= s.length <= 10^5
s 由小写英文字母组成
class Solution:
def validPalindrome(self, s: str) -> bool:
left=0
right=len(s)-1
while left<right and s[left]==s[right]:
left+=1
right-=1
if left==right:return True
return self.isvaid(s,left+1,right) or self.isvaid(s,left,right-1)
#key:aabba
def isvaid(self,s,left,right):
while left<right:
if s[left]!=s[right]:
return False
left,right=left+1,right-1
return True
lc 316 :去除重复字母
https://leetcode.cn/problems/remove-duplicate-letters/
提示:
1 <= s.length <= 10^4
s 由小写英文字母组成
class Solution:
def removeDuplicateLetters(self, s: str) -> str:
#统计字符的最后索引
lastIndex=[-1]*26
for i in range(len(s)):
lastIndex[ord(s[i])-ord('a')]=i
#
queue=deque()
exist=[False]*26
for i in range(len(s)):
if exist[ord(s[i])-ord('a')]:continue #queue已经有
#
while queue and queue[-1]>s[i] and lastIndex[ord(queue[-1])-ord('a')]>i:#key:后面已经有
c=queue.pop()
exist[ord(c)-ord('a')]=False
#
queue.append(s[i])
exist[ord(s[i])-ord('a')]=True
# #
res=''
while queue:
res+=queue.popleft()
return res #or:''.join(queue)
lc 1047:删除字符串中的所有相邻重复项
https://leetcode.cn/problems/remove-all-adjacent-duplicates-in-string/
提示:
1 <= S.length <= 20000
S 仅由小写英文字母组成。
#方案一:栈
class Solution:
def removeDuplicates(self, s: str) -> str:
queue=deque()
for c in s:
#key:else
if queue and queue[-1]==c:
queue.pop()
else:
queue.append(c)
return ''.join(queue)
#方案二:快慢指针
class Solution:
def removeDuplicates(self, s: str) -> str:
s=list(s)
slow=-1
fast=0
while fast<len(s):
if slow>=0 and s[slow]==s[fast]:
slow-=1
else:
slow+=1
s[slow]=s[fast]
fast+=1
return ''.join(s[:slow+1])
lc 1209 :删除字符串中的所有相邻重复项 II
https://leetcode.cn/problems/remove-all-adjacent-duplicates-in-string-ii/
提示:
1 <= s.length <= 10^5
2 <= k <= 10^4
s 中只含有小写英文字母。
#方案一:栈
#o(n),o(n)
class Solution:
def removeDuplicates(self, s: str, k: int) -> str:
stack=deque()
for c in s:
if not stack or c!=stack[-1][0]:
stack.append([c,1])
else:
stack[-1][1]+=1
if stack[-1][1]==k:
stack.pop()
#
res=''
for i in range(len(stack)):
curr=stack.popleft()
for cnt in range(curr[1]):
res +=curr[0]
return res
#方案二:快慢指针
class Solution:
def removeDuplicates(self, s: str, k: int) -> str:
stack=deque()
s=list(s)
#
slow=0
fast=0
while fast<len(s):
if slow!=fast:s[slow]=s[fast]
if slow==0 or s[slow]!=s[slow-1]:
stack.append(1)
else:
#key
sums=stack.pop()+1
if sums==k:
slow-=k
else:
stack.append(sums)
#实际‘同时更新’
fast+=1
slow+=1
return ''.join(s[0:slow])