一、检查相同字母间的距离
给你一个下标从 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 <= 52s仅由小写英文字母组成s中的每个字母恰好出现两次distance.length == 260 <= 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 种从 1 到 2 且恰好移动 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^51 <= 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)