Leetcode刷题第三天-贪心-双指针
738:单调递增
链接:738. 单调递增的数字 - 力扣(LeetCode)
嘶~介个介个恶心心,从后往前遍历,前一个数比当前数大,前一个数-1,当前数变为9
需要注意的是,保证每个9后面全是9
100,第一轮遍历完时90T_T
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class Solution: 2 def monotoneIncreasingDigits(self, n: int) -> int: 3 if(n<10): return n 4 nums=[] 5 tmp=n 6 while tmp: 7 nums.insert(0,tmp%10) 8 tmp=tmp//10 9 lens=len(nums) 10 i=lens-1 11 flage=False 12 while i>0: 13 if(nums[i-1]>nums[i]): 14 nums[i-1]-=1 15 nums[i]=9 16 flage=True 17 i-=1 18 n=0 19 start=False 20 for i in range(lens): 21 if(flage and nums[i]==9): 22 start=True 23 if(start): 24 n=n*10+9 25 else: 26 n=n*10+nums[i] 27 return n
968:监控二叉树
吐了,真的吐了,从未见过如次厚颜无耻之题
先是统计了每层节点个数,想按层安装,但是会出现子层节点少于父层节点,若在子层节点安装,还需要计算父-父层,跳不出来了T_T
然后迭代,后序遍历T_T左在前,左空的时候直接安到根上,右丢了,右在前,左空了,又跑根上了
最后递归,俩孩子有一个没有被覆盖,父就要安,俩孩子都被覆盖到了,父歇着就好,等待后续判断要不要安,其他情况父被覆盖,最后返回根的左右俩孩子状态,俩孩子都是0,根安T_T我真的已经哭死了
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 # Definition for a binary tree node. 2 # class TreeNode: 3 # def __init__(self, val=0, left=None, right=None): 4 # self.val = val 5 # self.left = left 6 # self.right = right 7 class Solution: 8 def minCameraCover(self, root: Optional[TreeNode]) -> int: 9 re=[0] 10 if(self.help(root,re)==0): re[0]+=1 11 return re[0] 12 13 def help(self,root,re): 14 if(not root): return 2 15 left=self.help(root.left,re) 16 right=self.help(root.right,re) 17 #左右都有覆盖,当前什么都不做 18 if(left==2 and right==2): 19 return 0 20 #左右有一个没覆盖,自己有摄像头 21 elif(left==0 or right==0): 22 re[0]+=1 23 return 1 24 else: 25 #左右有一个摄像头,自己被覆盖 26 return 2
更新迭代做法
利用数组(python没有栈,数组就好)pop()取最后加入数组得元素,按照【根空右左】顺序加入数组,左右节点空不加,在根节点后面加入一个空值作为标记,当从数组种取出得元素为空时,证明他的左右节点已经判断完,需要对当前节点进行判断
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 # Definition for a binary tree node. 2 # class TreeNode: 3 # def __init__(self, val=0, left=None, right=None): 4 # self.val = val 5 # self.left = left 6 # self.right = right 7 class Solution: 8 def minCameraCover(self, root: Optional[TreeNode]) -> int: 9 if(not root): return 0 10 sums=0 11 stack=[root] 12 while stack: 13 cur=stack.pop() 14 if(cur): 15 stack.append(cur) 16 #插入一个空节点,作为标记,遇到空节点就要开始判断是否安摄像头 17 stack.append(None) 18 #左右孩子入栈,空不入 19 if(cur.right): stack.append(cur.right) 20 if(cur.left): stack.append(cur.left) 21 else: 22 #遇到空,继续取最后一个,判断自己是否安 23 cur=stack.pop() 24 left,right=2,2 25 if(cur.left): left=cur.left.val 26 if(cur.right): right=cur.right.val 27 if(left==0 or right==0): 28 sums+=1 29 cur.val=1 30 elif(left==2 and right==2): 31 cur.val=0 32 #栈空,说明到最后一个根节点,左右孩子被覆盖但是没有摄像头,自己没有被覆盖,所以自己还要安一个 33 if(not stack): sums+=1 34 else: 35 cur.val=2 36 return sums
不行了,需要换个脑子了,开始双指针之旅
167:两个数之和
链接:167. 两数之和 II - 输入有序数组 - 力扣(LeetCode)
(⊙﹏⊙)就两头开始加
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class Solution: 2 def twoSum(self, numbers: List[int], target: int) -> List[int]: 3 if(not numbers): return numbers 4 left,right=0,len(numbers)-1 5 while True: 6 if(left==right): break 7 if(numbers[left]+numbers[right]==target): return [left+1,right+1] 8 elif(numbers[left]+numbers[right]>target): right-=1 9 else: left+=1 10 return [] 11 12
142:环形链表
链接:142. 环形链表 II - 力扣(LeetCode)
俩个指针,快的每次走两步,慢的每次走一步,链表有环,快的会再比慢的多走n个环的距离时相遇(跑步套圈)
找环的入口:从头再来一个指针3,也是每次都走一步,指针3和慢指针相遇的时候,比慢指针少走了一个环,相遇位置就是环口
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 # Definition for singly-linked list. 2 # class ListNode: 3 # def __init__(self, x): 4 # self.val = x 5 # self.next = None 6 7 class Solution: 8 def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]: 9 if(not head): return None 10 start,link=head,head 11 while link and link.next: 12 link=link.next.next 13 start=start.next 14 if(link==start): 15 start=head 16 while start!=link: 17 start=start.next 18 link=link.next 19 return link 20 return None 21 22
76:最小覆盖字串
更新更新,把一坨更新了一下,终于可以看清了T_T
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class Solution(object): 2 def minWindow(self,s,t): 3 if(not s): return "" 4 #t长度,要找到得字符得个数 5 lent=len(t) 6 lens=len(s) 7 if(lens<lent): return "" 8 #记录t中每个字母出现得频率 9 flage={x:t.count(x) for x in t} 10 left,minleft,minright=0,-1,lens 11 for right in range(lens): 12 #遍历s,开始移动右边界,如果当前得字符在t中,对应频率数组-1,如果频率大于0,要找得字符个数-1 13 if(s[right] in t): 14 flage[s[right]]-=1 15 if(flage[s[right]]>=0): lent-=1 16 #要找得字符个数为0时,当前[left,right]范围内包含全部得t中字符,闭区间 17 if(lent==0): 18 while left<=right: 19 #开始移动左边界,如果当前字符在t中,并且lent==0,表示为当前满足题意左边界最大值,判断当前窗口和要窗口大小,谁小取谁,并且频率数组+1,表示左边界开始移动,目标窗口内得字符个数减少 20 if(s[left] in t): 21 if(minright-minleft>right-left and lent==0): 22 minright=right 23 minleft=left 24 flage[s[left]]+=1 25 #当字符频率大于0时,表示当前窗口缺少这个字符,要找得字符长度+1 26 if(flage[s[left]]>0): lent+=1 27 left+=1 28 #要找得字符个数大于0,结束循环 29 if(lent>0): break 30 #右边界为s长度,表示没有合适得长度 31 if(minright==lens): return "" 32 return s[minleft:minright+1]