学习来源:
leetcode官方题解
评论区大佬的题解
5468
朴素方法:遍历存储数组中缺失的数字,若K
在其中则返回,否则利用数组最后一个数值计算K
。
tmp = []
# 遍历存储缺失值
for i in range(1,arr[-1]+1):
if i not in arr:
tmp.append(i)
# 查找K是否在tmp中
lens = len(tmp)
for i in range(1,lens+1):
if i == k:
return tmp[i-1]
# 若不在其中则,利用最后一个值与tmp中的元素个数计算K
return arr[-1] + (k-lens)
分情况讨论优化:缺失数字的位置无非3种位置:数组前,数组范围内和数组之后。因为数组严格递增,所以数组中元素值减去索引再减去1
即为当前元素之前缺失的数值个数。
# 缺失数字在数组前
if k <= arr[0] - 1:
return k
# 缺失数字在数组中
for i in range(len(arr)):
if arr[i] - i - 1 >= k:
'''
若当前arr[i]之前所缺失的数值个数大于K,则首先计算arr[i-1]之前缺失了多少数值
那么此时arr[i-1]与arr[i]之间缺少了:(k - (arr[i-1] - (i-1) - 1)) 个
所以所求数值为:arr[i-1] + (k - (arr[i-1] - (i-1) - 1)),化简即为i + k
'''
return i + k
# 缺失数字在数组后
return len(arr) + k # arr[-1] + (k - (arr[-1] - (len(arr)-1) - 1))
5469:K次操作转变字符串
该题首先需要准确理解题意,理解示例的计算过程。
题目解释:
- 一共有
K
轮操作机会,每轮操作(假设是第i
轮)只能选择:对某一未更改过的字符,修改i
次,或者,不修改任何字符。 - 每次修改,只能是向后替换
i
次。(a
向后替换1
次变为b
,……,z
向后替换1
次变为a
)`
示例1
解释:K=9
,因此一共有9
轮操作机会。字符串s='input'
转换为字符串t='ouput'
,只需将字符i
转换6
次变为字符o
,将字符n
转换7
次变为字符u
,即可。
第1轮:此时要么修改某一未修改过的字符1
次,要么不修改。发现字符串s
中没有需要修改1
次的字符。
第2轮:此时要么修改某一未修改过的字符2
次,要么不修改。发现字符串s
中没有需要修改2
次的字符。
……
第6轮:此时要么修改某一未修改过的字符6
次,要么不修改。修改字符i
。
第7轮:此时要么修改某一未修改过的字符7
次,要么不修改。修改字符n
。
综上,朴素解法不难写出:
lens = len(s)
lent = len(t)
if lens != lent:
return false
# 记录进行修改的字符
charlist = dict()
# 遍历字符串s
for i in range(lens):
if ord(t[i]) == ord(s[i]):
continue
# 计算需要修该几次,并查看记录中该次数是否已经使用
res = (ord(t[i]) + 26 - ord(s[i])) % 26
if res in charlist:
# 已经使用,则需要多转换26次
charlist[res] += 1
res += charlist[res]*26
else:
# 没有使用,进行记录
charlist[res] = 0
# 判断该修改轮次是否可达
if res > k:
return false
return true
5470
左右括号匹配,两个右括号可以匹配一个左括号。括号类问题经常使用堆栈来做,本题中其实可以使用一个变量,记录左括号的个数,减少空间使用。
lens = len(s)
ind = 0 # 当前索引
stack = [] # 记录左括号
res = 0 # 最终结果
while ind<lens:
if s[ind] == '(': # 遇到左括号就存入
stack.append(s[ind])
ind += 1 # 更新索引
else:
if ind+1 < lens and s[ind+1] == ')':
ind += 2 # 若为两个右括号,则完成匹配,索引向后更新2位
else:
res += 1 # 加1个右括号,完成匹配,索引只需更新1位
ind += 1
# 完成1次匹配,从stack中弹出一个左括号
if stack:
stack.pop(-1)
else:
res += 1 # 若当前stack中为空,则补全
res += len(stack)*2 # 若左括号有剩余,则添加两倍数量的右括号
return res
1542
tips
:状态压缩——用二进制数字表示有限个二态事物当前所处的状态。
举例说明:
假设有5盏灯,每盏灯存在亮灭两种状态,那么就可以使用5位二进制数进行表示。比如使用00000(2)
表示5盏灯都是熄灭状态,使用11111(2)
表示5盏灯都是工作状态。
本题:可以构成回文串的条件就是所有字符中,出现奇数次的字符数小于等于1。因为只需关心0~9
这10个数字出现的次数是否为奇数。可见这是有限个字符的二态表示,因此可以使用状态压缩。用0
表示当前数出现的次数为偶数,1
表示当前数出现的次数为奇数。如“1234567890”
,对应的二进制数值为:1111111111
,其中0~9
出现的次数均是奇数,用1表示;“112334455”
对应的二进制数为0000000100
,其中2出现的次数均是奇数,用1表示,其余为0。
算法思想:
- 两个相同的状态表示之间所增加的字符必定都是偶数个。
- 两个只错1位的状态表示之间所增加的字符必定只有1个是奇数个。
举例说明:
- 原始字符串“1”,对应的状态表示:“0000000010”。所增加字符均为偶数个(0022)。新的字符串“10022”,对应的状态表示:“0000000010”。
- 原始字符串“1”,对应的状态表示:“0000000010”。所增加字符存在一个为奇数个(00223)。新的字符串“100223”,对应的状态表示:“0000001010”。
cur_status_ind = {0:-1} # 初始化,便于计算s[0]。这里最好结合示例走一遍
res = 1 # 答案最少为1
status = 0 # 初始化压缩表示
for i in range(len(s)):
status ^= 1<<(ord(s[i]) - ord('0'))
# 若记录中存在status,则增加的必定是回文串,更新res
if status in cur_status_ind:
res = max(res, i - cur_status_ind[status])
else:
cur_status_ind[status] = i
# 若记录中存在与new_status相差1位的status,则增加的必定是回文串,更新res
for j in range(10):
new_status = status ^ (1<<j)
if new_status in cur_status_ind:
res = max(res, i - cur_status_ind[new_status])
return res