【周赛】第158场-2019-10-13

目录

1-Split a String in Balanced Strings-easy。字符串

 2-Queens That Can Attack the King-medium。数组、网格

3-Dice Roll Simulation-medium。

4-Maximum Equal Frequency-hard。


1-Split a String in Balanced Strings-easy。字符串

Balanced strings are those who have equal quantity of 'L' and 'R' characters.

Given a balanced string s split it in the maximum amount of balanced strings.

Return the maximum amount of splitted balanced strings.

Example 1:

Input: s = "RLRRLLRLRL"
Output: 4
Explanation: s can be split into "RL", "RRLL", "RL", "RL", each substring contains same number of 'L' and 'R'.

Example 2:

Input: s = "RLLLLRRRLR"
Output: 3
Explanation: s can be split into "RL", "LLLRRR", "LR", each substring contains same number of 'L' and 'R'.

Example 3:

Input: s = "LLLLRRRR"
Output: 1
Explanation: s can be split into "LLLLRRRR".

Constraints:

  • 1 <= s.length <= 1000
  • s[i] = 'L' or 'R'

因为是求最大个数,所以要把子段切分得尽量小才行,贪心法则在这里奏效,一旦找到平衡的res就加一,然后LR的计数清0

class Solution(object):
    def balancedStringSplit(self, s):
        """
        :type s: str
        :rtype: int
        """
        if not s:
            return 0
        balance = 0
        res = 0
        for c in s:
            if c == 'L':
                balance += 1
            else:
                balance -= 1
            if balance == 0:
                res += 1
                balance = 0
        return res

 2-Queens That Can Attack the King-medium。数组、网格

On an 8x8 chessboard, there can be multiple Black Queens and one White King.

Given an array of integer coordinates queens that represents the positions of the Black Queens, and a pair of coordinates king that represent the position of the White King, return the coordinates of all the queens (in any order) that can attack the King.

Example 1:

Input: queens = [[0,1],[1,0],[4,0],[0,4],[3,3],[2,4]], king = [0,0]
Output: [[0,1],[1,0],[3,3]]
Explanation:  
The queen at [0,1] can attack the king cause they're in the same row. 
The queen at [1,0] can attack the king cause they're in the same column. 
The queen at [3,3] can attack the king cause they're in the same diagnal. 
The queen at [0,4] can't attack the king cause it's blocked by the queen at [0,1]. 
The queen at [4,0] can't attack the king cause it's blocked by the queen at [1,0]. 
The queen at [2,4] can't attack the king cause it's not in the same row/column/diagnal as the king.

Example 2:

Input: queens = [[0,0],[1,1],[2,2],[3,4],[3,5],[4,4],[4,5]], king = [3,3]
Output: [[2,2],[3,4],[4,4]]

Example 3:

Input: queens = [[5,6],[7,7],[2,1],[0,7],[1,6],[5,1],[3,7],[0,3],[4,0],[1,2],[6,3],[5,0],[0,4],[2,2],[1,1],[6,4],[5,4],[0,0],[2,6],[4,5],[5,2],[1,4],[7,5],[2,3],[0,5],[4,2],[1,0],[2,7],[0,1],[4,6],[6,1],[0,6],[4,3],[1,7]], king = [3,4]
Output: [[2,3],[1,4],[1,6],[3,7],[4,3],[5,4],[4,5]]

Constraints:

  • 1 <= queens.length <= 63
  • queens[0].length == 2
  • 0 <= queens[i][j] < 8
  • king.length == 2
  • 0 <= king[0], king[1] < 8
  • At most one piece is allowed in a cell.

 比较虚张声势的一题,其实就是求距离King坐标最近的一圈Q的8个坐标,如果存在的话。考点是如何把代码写得更简洁和判断第一第二对称轴的公式

  • 遍历所有坐标判断是否是距离King最近的一周,是的话就更新
  • 注意输入的数据范围,最多不超过8*8的网格,所以转换思路,从King出发,一圈一圈往外找找到了该个方向的就继续找下一个方向。
# DIY
class Solution(object):
    def queensAttacktheKing(self, queens, king):
        """
        :type queens: List[List[int]]
        :type king: List[int]
        :rtype: List[List[int]]
        """
        if not queens or not king:
            return 0
        res = []
        up = [None, king[1]]
        down = [None, king[1]]
        left = [king[0], None]
        right = [king[0], None]
        left_up_dia = [None, None]
        left_down_dia = [None, None]
        right_up_dia = [None, None]
        right_down_dia = [None, None]
        for q in queens:
            if q[0] == king[0]:
                if q[1] < king[1]:
                    if left[1] == None:
                        left[1] = q[1]
                    else:
                        left[1] = max(left[1], q[1])
                else:
                    if right[1] == None:
                        right[1] = q[1]
                    else:
                        right[1] = min(right[1], q[1])
            elif q[1] == king[1]:
                if q[0] < king[0]:
                    if up[0] == None:
                        up[0] = q[0]
                    else:
                        up[0] = max(up[0], q[0])
                else:
                    if down[0] == None:
                        down[0] = q[0]
                    else:
                        down[0] = min(down[0], q[0])
            elif q[1] - q[0] == king[1] - king[0]:
                if q[0] < king[0]:
                    if left_up_dia[0] == None:
                        left_up_dia[0] = q[0]
                        left_up_dia[1] = q[1]
                    else:
                        if q[0] > left_up_dia[0]:
                            left_up_dia[0] = q[0]
                            left_up_dia[1] = q[1]
                else:
                    if right_down_dia[0] == None:
                        right_down_dia[0] = q[0]
                        right_down_dia[1] = q[1]
                    else:
                        if q[0] < right_down_dia[0]:
                            right_down_dia[0] = q[0]
                            right_down_dia[1] = q[1]
            elif q[1] + q[0] == king[1] + king[0]:
                if q[0] < king[0]:
                    if left_down_dia[0] == None:
                        left_down_dia[0] = q[0]
                        left_down_dia[1] = q[1]
                    else:
                        if q[0] > left_down_dia[0]:
                            left_down_dia[0] = q[0]
                            left_down_dia[1] = q[1]
                else:
                    if right_up_dia[0] == None:
                        right_up_dia[0] = q[0]
                        right_up_dia[1] = q[1]
                    else:
                        if q[0] < right_up_dia[0]:
                            right_up_dia[0] = q[0]
                            right_up_dia[1] = q[1]
        if up[0] != None:
            res.append(up)
        if down[0] != None:
            res.append(down)
        if left[1] != None:
            res.append(left)
        if right[1] != None:
            res.append(right)
        if left_up_dia[0] != None:
            res.append(left_up_dia)
        if left_down_dia[0] != None:
            res.append(left_down_dia)
        if right_up_dia[0] != None:
            res.append(right_up_dia)
        if right_down_dia[0] != None:
            res.append(right_down_dia)
        return res

# 简洁的写法
class Solution(object):
    def queensAttacktheKing(self, queens, king):
        """
        :type queens: List[List[int]]
        :type king: List[int]
        :rtype: List[List[int]]
        """
        # 注意这里不能有[0, 0]
        around = [[-1, -1], [-1, 0], [-1, 1], [0, -1], [0, 1], [1, -1], [1, 0], [1, 1]]
        board = [[0 for _ in range(8)] for _ in range(8)]
        res = []
        for q in queens:
            board[q[0]][q[1]] = 1
        for i in range(8):
            k = 1
            while True:
                x = around[i][0] * k + king[0]
                y = around[i][1] * k + king[1]
                if x >= 0 and x < 8 and y >= 0 and y < 8:
                    if board[x][y]:
                        res.append([x, y])
                        break
                else:
                    break
                k += 1
        return res

3-Dice Roll Simulation-medium。DP

A die simulator generates a random number from 1 to 6 for each roll. You introduced a constraint to the generator such that it cannot roll the number i more than rollMax[i] (1-indexed) consecutive times. 

Given an array of integers rollMax and an integer n, return the number of distinct sequences that can be obtained with exact n rolls.

Two sequences are considered different if at least one element differs from each other. Since the answer may be too large, return it modulo 10^9 + 7.

Example 1:

Input: n = 2, rollMax = [1,1,2,2,2,3]
Output: 34
Explanation: There will be 2 rolls of die, if there are no constraints on the die, there are 6 * 6 = 36 possible combinations. In this case, looking at rollMax array, the numbers 1 and 2 appear at most once consecutively, therefore sequences (1,1) and (2,2) cannot occur, so the final answer is 36-2 = 34.

Example 2:

Input: n = 2, rollMax = [1,1,1,1,1,1]
Output: 30

Example 3:

Input: n = 3, rollMax = [1,1,1,2,2,3]
Output: 181

Constraints:

  • 1 <= n <= 5000
  • rollMax.length == 6
  • 1 <= rollMax[i] <= 15

初始思路是按照Catalan递推公式那样,重复数字为1、2、3、…n次这样累积出所有可能性,因为给定rollMax也可以知道1-6每个数最多出现多少次,根据最多出现多少次分组。这种想法在设计子问题的时候卡住了,因为并不能分解成T(k)*T(n-k)这种可能性相乘

  • 用3维数组,dp[i][j][k]表示摇色子i次,数字j连续出现k次(不确定),所以还没搞懂为什么这些可能性是直接相加而非乘性的关系。
class Solution(object):
    def dieSimulator(self, n, rollMax):
        """
        :type n: int
        :type rollMax: List[int]
        :rtype: int
        """
        if n < 0 or len(rollMax) != 6:
            return 0
        dp = [[[0 for _  in range(16)] for _ in range(6)] for _ in range(n+1)]
        MOD = 10**9 + 7
        dp[0][0][0] = 1
        for i in range(1, n+1):
            for k in range(6):
                for j in range(2, rollMax[k]+1):
                    dp[i][k][j] = dp[i-1][k][j-1]
                sums = 0
                for j in range(6):
                    if j == k and i != 1:
                        continue
                    for l in range(16):
                        sums += dp[i-1][j][l]
                        sums %= MOD
                dp[i][k][1] = sums
        res = 0
        for i in range(6):
            for j in range(16):
                res += dp[n][i][j]
                res %= MOD
        return res

4-Maximum Equal Frequency-hard。

Given an array nums of positive integers, return the longest possible length of an array prefix of nums, such that it is possible to remove exactly one element from this prefix so that every number that has appeared in it will have the same number of occurrences.

If after removing one element there are no remaining elements, it's still considered that every appeared number has the same number of ocurrences (0).

Example 1:

Input: nums = [2,2,1,1,5,3,3,5]
Output: 7
Explanation: For the subarray [2,2,1,1,5,3,3] of length 7, if we remove nums[4]=5, we will get [2,2,1,1,3,3], so that each number will appear exactly twice.

Example 2:

Input: nums = [1,1,1,2,2,2,3,3,3,4,4,4,5]
Output: 13

Example 3:

Input: nums = [1,1,1,2,2,2]
Output: 5

Example 4:

Input: nums = [10,2,8,9,3,8,1,5,2,3,7,6]
Output: 8

Constraints:

  • 2 <= nums.length <= 10^5
  • 1 <= nums[i] <= 10^5

初始想法就是前向后向遍历,但不能确定相通的频数是多少,不适用。

class Solution(object):
    def maxEqualFreq(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        if not nums:
            return 0
        n = len(nums)
        ca = [0]*(10**5+5)
        cb = [0]*(10**5+5)
        res = 1
        hv = mx = 0
        for i in range(n):
            tmp = nums[i]
            ca[tmp] += 1
            cb[ca[tmp]] += 1
            mx = max(mx, ca[tmp])
            if ca[tmp] == 1:
                hv += 1
            else:
                cb[ca[tmp]-1] -= 1
            if mx == 1 or (cb[1] == 1 and cb[mx] == hv-1) or (cb[mx] == 1 and cb[mx-1] == hv-1):
                res = i+1
        return res

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值