Pyhon-Leetcode-第193场周赛题(总结)

本周得分:7

5436. 一维数组的动态和[3分]

class Solution:
    def runningSum(self, nums: List[int]) -> List[int]:
        if len(nums) == 0:return [] #原地操作 O(N) O(1)
        sum_ = nums[0] 
        for i in range(1,len(nums)):
            sum_ = sum_ + nums[i]
            nums[i]  = sum_
        return nums

5437. 不同整数的最少数目[4分]

考点:哈希+排序 【贪心】

class Solution:
    def findLeastNumOfUniqueInts(self, arr: List[int], k: int) -> int:
        dic = collections.Counter(arr)
        ans = len(dic) #原始个数
        #从小到大排序
        dic = sorted(dic.items(),key = lambda x:x[1])
        count = k
        for key,value in dic:
            count -= value
            if count <0: break
            ans -= 1
        return ans

评论里面的大神说这种做法叫做:贪心。刚开始不明觉厉,但是仔细想了想,这个题体现的就是贪心想法。去掉的时候先去掉频率小的数字,这样保证了使用最小的个数(K)来使得整体的整数最少,直到(K)不能够去掉一个数字的时,就结束了。很像0-1背包价值最大问题。还是要多积累!!!

5438. 制作 m 束花所需的最少天数【5分】

未看题解之前:

	#####  贪心思想 会影响后面的计算,可能会出现[x,1,1,x] -> 制作不了 2,2的花束,但是理论上是可以的      
	if m*k == len(bloomDay):return max(bloomDay)
        max_ = max(bloomDay)
        min_ = min(bloomDay)
        #print(min_,max_)
        visited = [False for i in range(len(bloomDay))]
        for i in range(min_,max_+1):
            #new_b = [bloomDay[l]-i for l  in range(len(bloomDay))]
            count = 0 
            for j in range(0,len(bloomDay)):
                if new_b[j] >=bloomDay[j]  and not visited[j]:
                    count += 1
                else:
                    count = 0 ##不连续 
                if count>=k: 
                    m = m-1
                    for n in range(j,j-count,-1):
                        visited[n] = True
                    count = 0 ## 完成一组 
                #print(visited)
                if m==0: return i
        return -1 

看了之后: 最小就是鲜花开放的最短时间,最大就是鲜花最长时间,如果满足m*k小于鲜花个数,那么肯定能够找见满足题目要求的。利用二分查找,在最小和最大之间,进行选择。

选定一个时间后,判断该时间是否满足条件。check()函数。如果满足条件,那么就是天数可能还可以缩小,那么就有right=mid-1,如果天数不满足,那么就要放大天数,left= mid+1。直到找见满足条件的最小天数。

class Solution:
    def minDays(self, bloomDay: List[int], m: int, k: int) -> int:
        n = len(bloomDay)
        if m*k > n:return -1
        if m*k == n:return max(bloomDay)
        min_ = min(bloomDay)
        max_ = max(bloomDay)
        ans = 0 
        def check(mid,bloomDay,k,m): ##mid 是最小天数,k是相邻的量,m 是花束个数
            count = 0 
            for i in range(n): ## 从index=1开始,看一下是否可以凑成m束
                if bloomDay[i] <= mid:
                    count +=1
                else:
                    count = 0
                if count>=k:
                    m-=1
                    count = 0
                if m == 0:return True 
            return False 

        while(min_<=max_):
            mid = min_ + (max_-min_)//2
            if check(mid,bloomDay,k,m):
            ##检查mid天数,是否满足条件,如果满足则减少天数再次尝试
                max_ = mid-1
            else:
                min_= mid+1
        return min_ 

 

类似解法:1552. 两球之间的磁力  (3/4) 第202场周赛

class Solution:
    def maxDistance(self, position: List[int], m: int) -> int:
        ### 规定最大最小距离,在最大和最小距离中,找能够摆下所有球的距离
        ### 最大距离: (max - min)/(m-1)
        ### 最小距离:1  或者也可以计算 position[i+1]-postion[i] 中最小值
        ### 从最小距离和最大距离中,找满足能够塞下m个球的最大距离 ->利用二分来做
        ### check() 函数是用来 满足能够塞下m个球的
        ### 从i=0的位置开始算,只要距离>=distance 那么就可以放下一个球  
        if m == 1: return 
        if m == 2: return max(position)-min(position)
        position.sort()
        max_ = (position[len(position)-1]-position[0])//(m-1)
        min_ = 1 # 最小也是1 
        ans = 1
       
        def check(position,distance,m):
            i = 0
            count = 1
            for j in range(1,len(position)):
                if distance <= position[j] - position[i]:
                    count+=1 ## 按照顺序一个个摆球 
                    i = j
                    if count>=m:return True # it can save m 
            return False 

        while(min_<=max_):
            mid = min_ + (max_-min_)//2
            if check(position,mid,m): ## 以当前最小距离和最大距离的mid是否能够将球摆下,如果能 那么 将最小距离 扩大否则将最大距离 缩小
                ans = mid
                min_ = mid+1
            else:
                max_ = mid-1
        return ans 

5188. 树节点的第 K 个祖先【6分】

考点:LCA倍增法[最近公共祖先]。

我的想法:用dic去存每个节点对应的父节点,从node节点开始,向上回溯就行了。time is O(N)。

分析:但是测试中要求的不是一个查询,是一批查询,所以看似时间复杂度只有O(N),也不是很大。但是一批下来,可能就超出题目预期范围的时间了。因此,查询不能用下面的方法,而是要采用倍增法

class TreeAncestor:

    def __init__(self, n: int, parent: List[int]):
        self.dic ={}
        for i in range(0,n):
            self.dic[i] = parent[i] #dic[节点]=父节点

    def getKthAncestor(self, node: int, k: int) -> int:
        count = k
        root = node
        #print(self.dic.keys())
        while(count>0 and root!=0): #O(N)
            root = self.dic[root]: # O(1)
            count -= 1 
        if count!=0:return -1
        else:return root
                    

下面是倍增法的主要解题代码。

class TreeAncestor:
 
    def __init__(self, n: int, parent: List[int]):
        self.dp = [[-1 for _ in range(0,20)] for _ in range(0,n)] #n,log2(50000)=20
        # 最深父节点不超过20
        for i in range(0,n): #节点的第1个父节点是parent
            self.dp[i][0] = parent[i]  #dic[节点]=父节点
        
        for j in range(1, 20): #构建2^1,2^2,2^3父节点
            for i in range(n):
                if self.dp[i][j-1] != -1:
                    self.dp[i][j] = self.dp[self.dp[i][j-1]][j-1]
 
    def getKthAncestor(self, node: int, k: int) -> int:
        for i in range(19, -1, -1):
            if k & (1 << i): ## k = 2^0+2^3,那么先跳到2^3,然后向下找,直到找到最近的.
                node = self.dp[node][i]
                if node == -1:
                    break
        return node

由于LCA问题,我是第一次接触,因此另外一篇文章写了LCA的一些问题和倍增法的详细介绍。如果需要参考,请查看此链接

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Foneone

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值