Leetcode-Python-第203场周赛

题目:2/4  排名:2069/5284

5495. 圆形赛道上经过次数最多的扇区

 我的想法:模拟了整个过程。从第一个rounds[i],rounds[i+1]开始,将经过的赛道个数相对应起来,找出最大的几个,返回。

时间复杂度:O(N^2)  空间复杂度:O(2N) dic + L 

class Solution:
    def mostVisited(self, n: int, rounds: List[int]) -> List[int]:
        dic ={} ## 每个扇区的经过的个数 
        for i in range(1,len(rounds)):  ##O(N^2)
            if rounds[i] > rounds[i-1]:
                for j in range(rounds[i-1]+1,rounds[i]+1):
                    dic[j] = dic.get(j,0)+1
            else:
                for j in range(rounds[i-1]+1,n+1):
                    dic[j] = dic.get(j,0)+1
                for j in range(1,rounds[i]+1):
                    dic[j] = dic.get(j,0)+1
        dic[rounds[0]] = dic.get(rounds[0],0) +1 
        L = sorted(dic.items(),key = lambda x:x[1],reverse = True)
        ans = []
        max_ = L[0][1]
        for i in range(0,len(L)):
            if L[i][1] == max_:
                ans.append(L[i][0])
            else:
                continue
        ans.sort()
        return ans

大神们的优化:

不管里面循环多少,圈是一个循环使用的,因此只需要看rounds[0]和rounds[-1]即可.

如果rounds[0]<=rounds[-1],则次数较多的为 rounds[0] -> roungs[-1]

如果rounds[0]>rounds[-1],则次数较多的为 1->rounds[-1]  and  round[0] ->n 

时间复杂度:O(N) 空间 O(1)

class Solution:
    def mostVisited(self, n: int, rounds: List[int]) -> List[int]:        
        ans = [] 
        if rounds[0] <= rounds[-1]:
            for i in range(rounds[0],rounds[-1]+1):
                ans.append(i)
        else: # rounds[0] > rounds[-1] -> (rounds[0],n+1) (1,rounds[-1]+1)
            for i in range(1,rounds[-1]+1):
                ans.append(i)
            for i in range(rounds[0],n+1):
                ans.append(i)
        return ans

1561. 你可以获得的最大硬币数目

贪心策略的题目。因为永远获得不了最大的那堆硬币,只能获得第二大的硬币。那么就让Bob 的硬币堆的数目尽可能小,则相对来说,就可以获得更多的硬币。 时间复杂度:O(NlogN) 空间复杂度:O(1) sort()函数时间复杂度为 O(NlogN)

class Solution:
    def maxCoins(self, piles: List[int]) -> int:
        count = 0
        piles.sort(reverse=True) ##
        n = len(piles)//3
        i = 1 
        while(n>0):
            count += piles[i]
            i+=2
            n-=1
        return count

评论和题解中有很多大佬用了list的切片操作。我觉得上面的已经足够了。

pileds.sort() ## 升
return sum(piles[len(piles)//3:][::2])

1562. 查找大小为 M 的最新分组

我的题解:暴力查找(超时) 时间复杂度O(N^2) 空间复杂度O(2N)

class Solution:
    def findLatestStep(self, arr: List[int], m: int) -> int:
        
        n = len(arr)
        if m == n: return n 
        l = [ '1' for i in range(n)]
        ans = ['F' for i in range(n+1)]
        def test(l,m,n):
            s = ''
            i = 0
            while(i<n):
                if l[i] == '0': i+=1
                else:
                    j = i
                    while(j<n and l[j]=='1'): j+=1 
                    if j-i ==m :return True
                    i = j
            return False 

        for i in range(-1,-n-1,-1):
            l[arr[i]-1] = '0'
            if test(l,m,n): ##存在
                return n+i
        return -1 

 代码参考自:https://leetcode-cn.com/problems/find-latest-group-of-size-m/solution/on-de-jie-jue-fang-fa-by-time-limit/

class Solution:
    def findLatestStep(self, arr: List[int], m: int) -> int:
        link = [-1]*len(arr) 
        ans = -1 ## 如果不存在,则返回-1,这里设置,体现不存在
        count = 0 
        for i in range(0,len(arr)):
            pos = arr[i] - 1
            L,R = pos,pos   
            link[pos] = pos #初始化,左右都是-1
            if pos>0 and link[pos-1] !=-1: ## 插入点左端不为0,插入点更新右端
                if (pos-1 - link[pos-1] +1) == m:
                    count -= 1 ##长度为m的少了           
                L  = link[pos-1] ## 左端指向R ,R ->pos
                #link[link[pos-1]] = R  #左端指向R
                #link[R] =  link[pos-1] ## 右端指向原来的L 
            if pos+1<len(arr) and link[pos+1]  != -1: ##插入点右端不为0,更新左端 
                if link[pos+1] - (pos+1) + 1 == m:
                    count -=1
                #link[L] = link[pos+1]
                #link[link[pos+1]] = L  
                R = link[pos+1]
            
            link[L] = R 
            link[R] = L ## 重新更新 link两端

            if R-L+1 == m: ## 如果将更新操作一次做完,那么两端这里有问题 
                count += 1
            if count>0: ## m 段的依旧存在,每次更新m存在的最大步骤 
                ans = i+1 
        return ans 

题目属于:区间合并、并查集查找类型。这类题目,要巧妙的用适当的指示link,来存储index。从而达到合并的目的,以及更新的目的。

其主要思想是: 在每次插入的过程中,针对每段'111'维护一个 link,其中 link[L] = R link[R] = L ,从link中就可以知道'111'的长度大小。

每次维护分为三种情况:

(1)左右两端都是-1,不用维护。link[pos]=pos

(2)插入1后,左边不是-1。右边是-1 与左边衔接。进行维护 link[L] 指向现在的R,link[R] 依旧是原来的指向

(3)插入1后,左边是-1,右边不是-1 与右边衔接。进行维护 link[L]指向原来的指向,link[R]指向现在的pos位置。

每一次都要判断,更新前 的长度以及更新后的长度,只要长度m存在就行。返回的就是最大的步骤。

并查集思想:https://blog.csdn.net/qq_41593380/article/details/81146850

1563. 石子游戏 V

直接写递归的方法会超时,故将每次递归的结果进行保留,以便不进入递归,直接输出。:递归+记忆化

为什么记忆化+递归 比DP更节约时间?因为DP是每个状态都要遍历,但是递归只遍历了涉及到的状态。

依旧超时了

class Solution:
    def stoneGameV(self, stoneValue: List[int]) -> int:
 
        def dfs(stoneValue,l,r,prev): ## index  
            if r == l :return 0  ### 只有一个石子 
            if r == l-1: # 两个石子 
                return min(stoneValue[r],stoneValue[l])
            if memo[l][r] !=-1 :return memo[l][r]
            res = 0 

            for i in range(l,r):
                left = 0
                for j in range(l,i+1):
                    left += stoneValue[j]
                right = 0
                for j in range(i+1,r+1) :
                    right += stoneValue[j]

                if left > right: ## 右侧继续做 
                    res =  max(res,right+dfs(stoneValue,i+1,r,prev))
                elif left == right:
                    res = max(res,left+max(dfs(stoneValue,l,i,prev),dfs(stoneValue,i+1,r,prev)))
                else:
                    res =  max(res,left+dfs(stoneValue,l,i,prev))
            memo[l][r] = res 
            return prev+res
         ## l,r index
        #if len(stoneValue)==1 :return 0 
        n = len(stoneValue)
        memo = [ [-1 for i in range(n)] for j in range(0,n)]
        a = dfs(stoneValue,0,n-1,0)
        return a

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
LeetCode-Editor是一种在线编码工具,它提供了一个用户友好的界面编写和运行代码。在使用LeetCode-Editor时,有时候会出现乱码的问题。 乱码的原因可能是由于编码格式不兼容或者编码错误导致的。在这种情况下,我们可以尝试以下几种解决方法: 1. 检查文件编码格式:首先,我们可以检查所编辑的文件的编码格式。通常来说,常用的编码格式有UTF-8和ASCII等。我们可以将编码格式更改为正确的格式。在LeetCode-Editor中,可以通过界面设置或编辑器设置来更改编码格式。 2. 使用正确的字符集:如果乱码是由于使用了不同的字符集导致的,我们可以尝试更改使用正确的字符集。常见的字符集如Unicode或者UTF-8等。在LeetCode-Editor中,可以在编辑器中选择正确的字符集。 3. 使用合适的编辑器:有时候,乱码问题可能与LeetCode-Editor自身相关。我们可以尝试使用其他编码工具,如Text Editor、Sublime Text或者IDE,看是否能够解决乱码问题。 4. 查找特殊字符:如果乱码问题只出现在某些特殊字符上,我们可以尝试找到并替换这些字符。通过仔细检查代码,我们可以找到导致乱码的特定字符,并进行修正或替换。 总之,解决LeetCode-Editor乱码问题的方法有很多。根据具体情况,我们可以尝试更改文件编码格式、使用正确的字符集、更换编辑器或者查找并替换特殊字符等方法来解决这个问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Foneone

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

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

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

打赏作者

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

抵扣说明:

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

余额充值