[Leetcode Weekly Contest]183

链接:LeetCode

[Leetcode]5376. 非递增顺序的最小子序列

给你一个数组 nums,请你从中抽取一个子序列,满足该子序列的元素之和 严格 大于未包含在该子序列中的各元素之和。如果存在多个解决方案,只需返回 长度最小 的子序列。如果仍然有多个解决方案,则返回 元素之和最大 的子序列。
与子数组不同的地方在于,「数组的子序列」不强调元素在原数组中的连续性,也就是说,它可以通过从数组中分离一些(也可能不分离)元素得到。
注意,题目数据保证满足所有约束条件的解决方案是 唯一 的。同时,返回的答案应当按 非递增顺序 排列。

排序不解释。

class Solution:
    def minSubsequence(self, nums: List[int]) -> List[int]:
        if len(nums)<2:
            return nums
        nums.sort(reverse=True)
        sum_ = sum(nums)
        res = []
        cur = 0
        for num in nums:
            res.append(num)
            cur += num
            if cur > sum_-cur:
                break
        return res

[Leetcode]5377. 将二进制表示减到 1 的步骤数

给你一个以二进制形式表示的数字 s 。请你返回按下述规则将其减少到 1 所需要的步骤数:
如果当前数字为偶数,则将其除以 2 。
如果当前数字为奇数,则将其加上 1 。
题目保证你总是可以按上述规则将测试用例变为 1 。

直接对二进制数组进行操作
偶数时,最后一位是'0',除以2即去掉最后一位,整体右移一个单位
奇数时,二进制加法,注意首位进位的问题

class Solution:
    def numSteps(self, s: str) -> int:
        tmp = 0
        while s != '1':
            if s[-1] == '0':
                s = s[:-1]
                tmp += 1
            else:
                tmp += 1
                ans = 1
                s = '0'+ s
                for i in range(len(s)-1,-1,-1):
                    if ans==1 and s[i]=='1':
                        s = s[:i]+'0'+s[i+1:]
                        ans = 1
                    elif ans==1 and s[i]=='0':
                        s = s[:i]+'1'+s[i+1:]
                        ans = 0
                    elif ans==0:
                        break
                if s[0] == '0':
                    s = s[1:]
        return tmp

[Leetcode]5195. 最长快乐字符串

如果字符串中不含有任何 'aaa','bbb' 或 'ccc' 这样的字符串作为子串,那么该字符串就是一个「快乐字符串」。
给你三个整数 a,b ,c,请你返回 任意一个 满足下列全部条件的字符串 s:
s 是一个尽可能长的快乐字符串。
s 中 最多 有a 个字母 'a'、b 个字母 'b'、c 个字母 'c' 。
s 中只含有 'a'、'b' 、'c' 三种字母。
如果不存在这样的字符串 s ,请返回一个空字符串 ""。

贪心,每一轮放置字符时优先先放剩余次数最多的, 如果上次放的2个字符和剩余个数最多的字符相同,则放置次多的字符

class Solution:
    def longestDiverseString(self, a: int, b: int, c: int) -> str:
        d = {'a':min(a,2*(b+c+1)),'b':min(b,2*(a+c+1)),'c':min(c,2*(b+a+1))}
        n = sum(d.values())
        res = []
        for i in range(n):
            cand = set(['a','b','c'])
            if len(res)>1 and res[-1]==res[-2]:
                cand.remove(res[-1])
            tmp = max(cand,key=lambda x:d[x])
            res.append(tmp)
            d[tmp] -= 1
        return ''.join(res)

[Leetcode]5379. 石子游戏 III

Alice 和 Bob 用几堆石子在做游戏。几堆石子排成一行,每堆石子都对应一个得分,由数组 stoneValue 给出。
Alice 和 Bob 轮流取石子,Alice 总是先开始。在每个玩家的回合中,该玩家可以拿走剩下石子中的的前 1、2 或 3 堆石子 。比赛一直持续到所有石头都被拿走。
每个玩家的最终得分为他所拿到的每堆石子的对应得分之和。每个玩家的初始分数都是 0 。比赛的目标是决出最高分,得分最高的选手将会赢得比赛,比赛也可能会出现平局。
假设 Alice 和 Bob 都采取 最优策略 。如果 Alice 赢了就返回 "Alice" ,Bob 赢了就返回 "Bob",平局(分数相同)返回 "Tie" 。

一开始,Alice 面临取1、2、3 堆的抉择,Alice 此刻总共能拿多少分,取决于取完 1 or 2 or 3 堆之后面对剩下的这堆石子精分出来的 Bob能拿多少分,因为剩下的分就是 Alice 的。
也就是 dp[i]=Max(sum-dp[i+1],sum-dp[i+2],sum-dp[i+3])dp[i]=Max(sum−dp[i+1],sum−dp[i+2],sum−dp[i+3]) ,dp[i]为石碓 i……n 得最高分数,sum 为 i……n 的石碓分数之和。
那 Alice 的得分即为:dp[0] ,Bob 得分为 sumAll-dp[0]。
这其实是个非常简单的动规。

class Solution:
    def stoneGameIII(self, stoneValue: List[int]) -> str:
        s = stoneValue
        su = 0
        dp = [0]*(len(s)+1)+[10000000]*4
        for i in range(len(s)-1, -1, -1):
            su += s[i]
            cho = min(dp[i+1],dp[i+2],dp[i+3])
            dp[i] = su - cho
        if dp[0]+dp[0]<su:
            return "Bob"
        elif dp[0]+dp[0]>su:
            return "Alice"
        return "Tie"

参考:
leetcode

posted @ 2020-04-06 10:27  Jamest  阅读(197)  评论(0编辑  收藏  举报