leetcode 1252题 解法 奇数值单元格的数目
奇数值单元格的数目
给你一个 n 行 m 列的矩阵,最开始的时候,每个单元格中的值都是 0。
另有一个索引数组 indices,indices[i] = [ri, ci] 中的 ri 和 ci 分别表示指定的行和列(从 0 开始编号)。
你需要将每对 [ri, ci] 指定的行和列上的所有单元格的值加 1。
请你在执行完所有 indices 指定的增量操作后,返回矩阵中 「奇数值单元格」 的数目。
解题思路:indices 里面的一个一个的值 表示 的 意思 要理解。题目说的很清楚。
解法1:
直接按照题目的意思一遍一遍的把数累加上去。
可以优化算法的地方:
注意一点因为判断奇数,所以 如果现在是 0 ,那么加 1 之后是 1。如果是 1 ,加 1 之后 是 0 .因为偶数么,相当于0.
def oddCells(n, m, indices):
lista=[[0 for i in range(m)] for i2 in range(n)] #初始化二维数组
for x in indices:
for y in range(m): #遍历行
if lista[x[0]][y]==0:
lista[x[0]][y]=1
else:
lista[x[0]][y]=0
for y2 in range(n):#遍历列
if lista[y2][x[1]]==0:
lista[y2][x[1]]=1
else:
lista[y2][x[1]]=0
sum=0
for x in range(n): #最后统计一遍所有的 1
for y in range(m):
sum+=lista[x][y]
return sum
oddCells(2,2,[[1,1],[0,0]])
此种解法,好像只能击败 15%以上的选手,所有该算法有改进的空间。
解法2:
如果从开始的时候就对 indices 里面的数值进行优化,效果会更好些。
分别定义2个list a1,a2,用来记录 indices 里面描述行 和 列的 信息。
先把行的值 都添加进 a1,
如果 x 在 a1 里面了,那么 两相抵消。直接把 a1里面的x删除了即可。如果不在a1里面,就添加进a1。
如果 x 在 a2 里面了,那么 两相抵消。直接把 a2里面的x删除了即可。如果不在a2里面,就添加进a2。
最后
a1 相当于需要修改 1 次的行的集合
a2 相当于需要修改 1 次的列的集合
然后,开始把 改 加 1 的,放进一个新的二维数组lista。
最后 再遍历一遍里面的里面的所有1
def oddCells(n, m, indices):
lista=[[0 for i in range(m)] for i2 in range(n)] #初始化二维数组
a1=[]
a2=[]
for x in indices:
if x[0] in a1:
a1.remove(x[0])
else:
a1.append(x[0])
if x[1] in a2:
a2.remove(x[1])
else:
a2.append(x[1])
for x in a1:
for y in range(m):
if lista[x][y]==0:
lista[x][y]=1
else:
lista[x][y]=0
for x in a2:
for y in range(n):
if lista[y][x]==0:
lista[y][x]=1
else:
lista[y][x]=0
suma=0
for x in range(n):
for y in range(m):
suma+=lista[x][y]
return suma
oddCells(2,3,[[0,1],[1,1]])
但是这种接法也只是击败了85%的选手。
解法3
如果我们可以确定 需要变换的 行数 和列数。那就意味着,行数*m+列数*n 就是变换后的点的数量。
当然里面有重复的,
重点: 重复的包括两个方面的
1、行列交汇的点 被重复计算了,所有减去 行数*列数
2、重复的点 结果应该是2,变化了2次,所以还要 再减去 行数*列数
def oddCells(n, m, indices):
a1=[]
a2=[]
for x in indices:
if x[0] in a1:
a1.remove(x[0])
else:
a1.append(x[0])
if x[1] in a2:
a2.remove(x[1])
else:
a2.append(x[1])
x=len(a1)
y=len(a2)
return x*m+y*n-2*x*y
oddCells(2,2,[[1,1],[0,0]])
这次的结果才最终击败了99%的选手!