日渐头秃的代码日记--第309场周赛

138 阅读3分钟

一、检查相同字母间的距离

给你一个下标从 0 开始的字符串 s ,该字符串仅由小写英文字母组成,s 中的每个字母都 恰好 出现 两次 。另给你一个下标从 0 开始、长度为 26 的的整数数组 distance 。

字母表中的每个字母按从 0 到 25 依次编号(即,'a' -> 0'b' -> 1'c' -> 2, ... , 'z' -> 25)。

在一个 匀整 字符串中,第 i 个字母的两次出现之间的字母数量是 distance[i] 。如果第 i 个字母没有在 s 中出现,那么 distance[i] 可以 忽略 。

如果 s 是一个 匀整 字符串,返回 true ;否则,返回 false 。

 

示例 1:

输入: s = "abaccb", distance = [1,3,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
输出: true
解释:
- 'a' 在下标 0 和下标 2 处出现,所以满足 distance[0] = 1 。
- 'b' 在下标 1 和下标 5 处出现,所以满足 distance[1] = 3 。
- 'c' 在下标 3 和下标 4 处出现,所以满足 distance[2] = 0 。
注意 distance[3] = 5 ,但是由于 'd' 没有在 s 中出现,可以忽略。
因为 s 是一个匀整字符串,返回 true

示例 2:

输入: s = "aa", distance = [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
输出: false
解释:
- 'a' 在下标 0 和 1 处出现,所以两次出现之间的字母数量为 0 。
但是 distance[0] = 1 ,s 不是一个匀整字符串。

 

提示:

  • 2 <= s.length <= 52
  • s 仅由小写英文字母组成
  • s 中的每个字母恰好出现两次
  • distance.length == 26
  • 0 <= distance[i] <= 50

解析

按照题目意思模拟就行了

代码

from collections import defaultdict
class Solution:
    def checkDistances(self, s: str, distance: List[int]) -> bool:
        position = defaultdict(list)
        for index, c in enumerate(s):
            position[c].append(index)
        alpha = "abcdefghijklmnopqrstuvwxyz"
        res = True
        for index, dist in enumerate(distance):
            if alpha[index] not in s:
                continue
            else:
                d = position[alpha[index]][1] - position[alpha[index]][0]
                if dist == d - 1:
                    continue
                else:
                    res = False
                    break
        return res

二、恰好移动 k 步到达某一位置的方法数目

给你两个  整数 startPos 和 endPos 。最初,你站在 无限 数轴上位置 startPos 处。在一步移动中,你可以向左或者向右移动一个位置。

给你一个正整数 k ,返回从 startPos 出发、恰好 移动 k 步并到达 endPos 的 不同 方法数目。由于答案可能会很大,返回对 10^9 + 7 取余 的结果。

如果所执行移动的顺序不完全相同,则认为两种方法不同。

注意: 数轴包含负整数

 

示例 1:

输入: startPos = 1, endPos = 2, k = 3
输出: 3
解释: 存在 3 种从 12 且恰好移动 3 步的方法:
- 1 -> 2 -> 3 -> 2.
- 1 -> 2 -> 1 -> 2.
- 1 -> 0 -> 1 -> 2.
可以证明不存在其他方法,所以返回 3

示例 2:

输入: startPos = 2, endPos = 5, k = 10
输出: 0
解释: 不存在从 2 到 5 且恰好移动 10 步的方法。

 

提示:

  • 1 <= startPos, endPos, k <= 1000

解析

这道题目思路不难,就是数学里的基础的排列组合问题,组合数C(n, r)公式一算就ok了。出现问题的地方是python的乘法。。。大坑,数字大了之后乘法乘不准,除法除不准的。

代码

import math
class Solution:
    def numberOfWays(self, startPos: int, endPos: int, k: int) -> int:
        self.mod = 10**9+7
        if k < abs(endPos - startPos):
            return 0
        elif k == abs(endPos - startPos):
            return 1
        else:
            s = abs(endPos - startPos)
            if (k - s) % 2 != 0:
                return 0
            else:
                l = int((k-s) / 2)
                res = math.comb(k, l) % self.mod
                return res

三、最长优雅子数组

给你一个由  整数组成的数组 nums 。

如果 nums 的子数组中位于 不同 位置的每对元素按位 与(AND) 运算的结果等于 0 ,则称该子数组为 优雅 子数组。

返回 最长 的优雅子数组的长度。

子数组 是数组中的一个 连续 部分。

注意: 长度为 1 的子数组始终视作优雅子数组。

 

示例 1:

输入: nums = [1,3,8,48,10]
输出: 3
解释: 最长的优雅子数组是 [3,8,48] 。子数组满足题目条件:
- 3 AND 8 = 0
- 3 AND 48 = 0
- 8 AND 48 = 0
可以证明不存在更长的优雅子数组,所以返回 3 。

示例 2:

输入: nums = [3,1,5,11,13]
输出: 1
解释: 最长的优雅子数组长度为 1 ,任何长度为 1 的子数组都满足题目条件。

 

提示:

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

解析

二进制对应位置上的1的数量不能超过1,找出最长的连续符合条件的数组长度。可以采用双指针遍历的方法。

代码

class Solution:
    MAXSTEP = 30
    def isNice(self):
        for n in self.bits:
            if n > 1:
                return False
        return True
    def binaryAdd(self, num):
        for i in range(self.MAXSTEP):
            self.bits[i] += num >> i & 1
    def binaryMinus(self, num):
        for i in range(self.MAXSTEP):
            self.bits[i] -= num >> i & 1
        
    def longestNiceSubarray(self, nums: List[int]) -> int:
        if len(nums) == 1:
            return 1
        self.bits = [0] * self.MAXSTEP  # 2**30 > 10**9
        j = 0
        res = []
        for index, num in enumerate(nums):
            self.binaryAdd(num)
            # print(self.bits)
            while j < index and not self.isNice():
                self.binaryMinus(nums[j])
                # print("after minus %s, %s" % (nums[j], self.bits))
                j += 1
            res.append(index-j+1)
        print(res)
        return max(res)