记录了初步解题思路 以及本地实现代码;并不一定为最优 也希望大家能一起探讨 一起进步
目录
- 5/24 664. Strange Printer 奇怪的打印机
- 5/25 1787. Make the XOR of All Segments Equal to Zero 使所有区间的异或结果为零
- 5/26 1190. Reverse Substrings Between Each Pair of Parentheses 反转每对括号间的子串
- 5/27 461. Hamming Distance 汉明距离
- 5/28 477. Total Hamming Distance 汉明距离总和
- 5/29 1074. Number of Submatrices That Sum to Target 元素和为目标值的子矩阵数量
- 5/30
5/24 664. Strange Printer 奇怪的打印机
动态规划
如果只有一个字符a 那么只需打印一次
如果字符串abcdefa头尾相同 那么与去掉尾部的情况abcdef是相同的
起始位置i从后向前遍历
i往前移动一步 意味着在开头位置增加一个字符
最坏的情况就是前一种情况下多打印一次
此时再判断中间位置k的值 如果与i相同判断是否可以缩小
def strangePrinter(s):
"""
:type s: str
:rtype: int
"""
n = len(s)
dp = [[float('inf')]*n for _ in range(n)]
for i in range(n-1,-1,-1):
dp[i][i]=1
for j in range(i+1,n):
if s[i]==s[j]:
dp[i][j] =dp[i][j-1]
continue
dp[i][j] = dp[i+1][j]+1 #多印一次
for k in range(i+1,j+1):
if s[i]==s[k]:
if k<j:
dp[i][j] = min(dp[i][j],dp[i][k]+dp[k+1][j])
else:
dp[i][j] = min(dp[i][j],dp[i][k-1])
return dp[0][n-1]
5/25 1787. Make the XOR of All Segments Equal to Zero 使所有区间的异或结果为零
num[i]…num[i+k-1]=0
num[i+1]…num[i+k]=0
两式异或 得到num[i]^num[i+k]=0 说明每隔k个数 必定相等
将所有间隔k的数分为1组 一共k组
得到每一组内出现最多的数(众数)的次数 zs 总数个数-众数次数总和 及将每组数变为一致(众数)需要改变的最少次数
每一组数改变为每组众数的值 此时有可能无法满足 k组数异或值为0
zs[0]zs[1]…^zs[k-1] = 0
需要牺牲一组 zs[i]
将这一组全部变为能够使k组数异或为0的值 zs[i] = zs[0]…zs[i-1]zs[i+1]…^zs[k-1]
keys 记录每一组内每个数出现的次数
考虑将该组从众数变为key时 是否能够减少次数
def minChanges(nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: int
"""
from collections import Counter
from collections import defaultdict
n = len(nums)
count = defaultdict(Counter)
for i in range(k):
for j in range(i,n,k):
count[i][nums[j]]+=1
#每组数中的众数 数量
zs = [count[i].most_common(1)[0][1] for i in range(k)]
ans = n - sum(zs) #将每组数变为当前组的众数 需要改变的个数
keys = [sorted(count[i].keys(),key=lambda x:-count[i][x]) for i in range(k)]
#为了使得k个数异或为0 需要牺牲其中一组数
def dfs(idx,curr):
if idx==k and curr==0:
return 0
elif idx==k:
return float('inf')
res = zs[idx]
for key in keys[idx]:
if zs[idx]-count[idx][key] >= res:
continue
res = min(res,dfs(idx+1,curr^key)-count[idx][key]+zs[idx])
return res
return ans+dfs(0,0)
5/26 1190. Reverse Substrings Between Each Pair of Parentheses 反转每对括号间的子串
栈
遇到’(’ 将当前num放入栈中,重新记录后续的数值num
遇到’)’ 将记录的字符串num翻转 并从栈中取出一个连接到头部
def reverseParentheses(s):
"""
:type s: str
:rtype: str
"""
ans = []
num=''
for i in s:
if i=='(':
ans.append(num)
num=''
elif i==')':
a = ans.pop()
num = num[::-1]
num = a+num
else:
num+=i
return num
5/27 461. Hamming Distance 汉明距离
计算两数异或之后 二进制表示有多少个1
数值s与s-1相与 能够消除最低位一个1
100100 & 100011 = 100000
def hammingDistance(x, y):
"""
:type x: int
:type y: int
:rtype: int
"""
s = x^y
ret = 0
while s>0:
ret += 1
s&=(s-1)
return ret
5/28 477. Total Hamming Distance 汉明距离总和
1.根据461计算两个数之间的汉明距离
枚举 超时
2.遍历每一个数
记录这个数每一个维度包含的0,1数量
3.遍历每一个维度 最多2^30
记录每一个数在该维度包含0,1的数量
“”"
def totalHammingDistance(nums):
"""
:type nums: List[int]
:rtype: int
"""
def hamming(x,y):
s = x^y
ret = 0
while s>0:
ret += 1
s&=(s-1)
return ret
ret = 0
for i in range(len(nums)-1):
for j in range(i+1,len(nums)):
ret+=hamming(nums[i],nums[j])
return ret
def totalHammingDistance2(nums):
"""
:type nums: List[int]
:rtype: int
"""
n=len(nums)
dim = {}
for num in nums:
loc =0
while num>0:
dim[loc] = dim.get(loc,0)+(num&1)
loc+=1
num>>=1
ret = 0
for v in dim.values():
ret += (n-v)*v
return ret
def totalHammingDistance3(nums):
"""
:type nums: List[int]
:rtype: int
"""
n = len(nums)
ret = 0
for i in range(30):
s=0
for num in nums:
s += (num>>i)&1
ret += s*(n-s)
return ret
5/29 1074. Number of Submatrices That Sum to Target 元素和为目标值的子矩阵数量
1.使用矩阵s 记录从原点到i,j的总和
左上角[x,y]到右下角[i,j]区域内的元素和:[i,j]-[x-1,j]-[i,y-1[+[x-1,y-1]
超时
2.设置上下边界 将每一列的数相加 从二维转化为一维
如
0,1,0 <-上边界
1,1,1 <-下边界
0,1,0
如果上下边界为0,1
可将这两行每一列相加 得到1,2,1
转化为在一位数组内 [i:j]的和为target
def numSubmatrixSumTarget(matrix, target):
"""
:type matrix: List[List[int]]
:type target: int
:rtype: int
"""
n = len(matrix)
m = len(matrix[0])
s = [[0]*(m+1) for _ in range(n+1)]
for i in range(n):
for j in range(m):
s[i+1][j+1] = s[i][j+1]+s[i+1][j]-s[i][j]+matrix[i][j]
ret = 0
for i in range(1,n+1):
for j in range(1,m+1):
for x in range(1,i+1):
for y in range(1,j+1):
ans = s[i][j]-s[x-1][j]-s[i][y-1]+s[x-1][y-1]
if ans == target:
#print(i,j,x,y)
ret+=1
return (ret)
def numSubmatrixSumTarget2(matrix, target):
"""
:type matrix: List[List[int]]
:type target: int
:rtype: int
"""
n = len(matrix)
m = len(matrix[0])
ret = 0
#在一维数组内寻找[i,j]和为target
def find(nums):
mem={}
mem[0]=1
pre = 0
count = 0
for c in nums:
pre +=c
if pre-target in mem:
count += mem[pre-target]
mem[pre] = mem.get(pre,0)+1
return count
#上边界
for i in range(n):
s = [0]*m
#下边界
for j in range(i,n):
for c in range(m):
#每一列相加
s[c] +=matrix[j][c]
ret += find(s)
return ret
5/30
map用来存放单词中的每一个字母
若为最后一个字母,加入标识 表示一个单词结束 方便搜索