持续更新中
题号 | 标题 | 题解 | 标签 | 难度 |
---|---|---|---|---|
0189 | 轮转数组 | Python | 数组 | 中等 |
0066 | 加一 | Python | 数组 | 简单 |
0724 | 寻找数组的中心下标 | Python | 数组 | 简单 |
0485 | 最大连续 1 的个数 | Python | 数组 | 简单 |
0238 | 除自身以外数组的乘积 | Python | 数组 | 中等 |
一开始犯了错误:注意python中数组的赋值
两个列表list1和list2,直接用等号赋值,list2修改后,list1也会被修改
[:]
或者.copy()
参考:python把一个数组赋值给另一个数组
一开始的错误代码
def rotate2( nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: None Do not return anything, modify nums in-place instead.
"""
nums2 = nums
for i in range(len(nums)):
nums2[i] = nums[(i+k+1)%len(nums)]
return nums2
rotate2([1,2,3,4,5,6,7],3)
[5, 6, 7, 5, 6, 7, 5]
来分析一下: nums2[0] = nums[4] , 这时候 nums2[0]和nums[0]都变成了5 ,所以nums2[3] = nums[0] = 5…
改了改,以为自己做对了,但是没AC
def rotate(nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: None Do not return anything, modify nums in-place instead.
"""
# nums2 = num
nums2 = []
for i in range(len(nums)):
nums2.append(0)
for i in range(len(nums)):
#下面这俩应该都可以
** nums2[i] = nums[(i+k+1) % len(nums)]
# nums2[(i+k)%len(nums)] = nums[i]**
return nums2
rotate([1,2,3,4,5,6,7],3)
[5, 6, 7, 1, 2, 3, 4]
难绷,审题! 去掉return就行了
算法通关手册上的python解法
class Solution:
def rotate(self, nums: List[int], k: int) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
n = len(nums)
k = k % n
self.reverse(nums, 0, n-1)
self.reverse(nums, 0, k-1)
self.reverse(nums, k, n-1)
def reverse(self, nums: List[int], left: int , right: int) -> None:
while left < right:
tmp = nums[left]
nums[left] = nums[right]
nums[right] = tmp
left += 1
right -=1
力扣题解区上面看到切片的解法,感觉very smart
class Solution:
def rotate(self, nums: List[int], k: int) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
k = k % len(nums)
nums[:] = nums[-k:] + nums[:-k]
一开始写的代码
class Solution:
def plusOne(self, digits: List[int]) -> List[int]:
k = len(digits)
sum = 0
m = 1
while k >= 1:
sum += m*digits[k-1]
m *= 10
k -= 1
newlis = []
sum += 1
j = 0
while sum > 0:
# newlis.append(sum % 10)
newlis.insert(j, sum % 10)
sum //=10
return newlis
看《算法通关手册》的题解
感觉思路很清晰
有可能有进位,先在前面放个0,末位加个1,啥时候会有进位呢,那个位置上的数字为10的时候,如果低位都没碰到10,那么高位肯定不会碰到10,直接break,返回原来的列表,即现在的digits[1:]
哪一位有进位,就把那一位变成0,然后它的前一位+1
如果会一直进位到最高位,那么就返回digits
def plusOne(self, digits: List[int]) -> List[int]:
digits = [0] + digits
digits[len(digits)-1] += 1
for i in range(len(digits)-1,0,-1):
if digits[i] != 10:
break
else:
digits[i] = 0
digits[i-1] += 1
if digits[0] == 0:
return digits[1:]
else:
return digits
注意 [0] + digits的顺序是有影响的
力扣官方题解 妙啊
思路
算法
只需要对数组 digits \textit{digits} digits进行一次逆序遍历,找出第一个不为 999 的元素,将其加一并将后续所有元素置零即可。如果 digits \textit{digits} digits中所有的元素均为 999,那么对应着「思路」部分的第三种情况,我们需要返回一个新的数组。
class Solution:
def plusOne(self, digits: List[int]) -> List[int]:
n = len(digits)
for i in range(n -1, -1, -1):
if digits[i] != 9:
digits[i] += 1
for j in range(i + 1, n):
digits[j] = 0
return digits
return [1] + [0] * n
在前面自己的解法那个代码里面
一开始的错误代码
- 一开始的代码
class Solution:
def pivotIndex(self, nums: List[int]) -> int:
suml = 0 # 从左往右的和
sumr = 0 # 从右往左的和
# l = len(nums)
lisl = []
lisr = []
for i in range(len(nums)):
suml += nums[i]
lisl.append(suml)
for i in range(len(nums)-1,-1,-1):
sumr += nums[i]
lisr.append(sumr)
# flag = 0
if lisl[0] == lisl[len(nums)-1]:
return 0
elif lisr[0] == lisr[len(nums)-1]:
return len(nums)-1
else:
for j in range(len(nums)):
if lisl[j] == lisr[j]:
return j
return -1
lisl=[1,8,11,17,22,28]
lisr=[6,11,17,20,21,28]
返回5是不正确的,突然发现自己这个代码只适合中心点两边元素个数相等的情况…
按照那个思路,在左和数组and 右和数组相同位置的话,那只能是元素个数相同了
改了改,还是有问题
class Solution:
def pivotIndex(self, nums: List[int]) -> int:
suml = 0 # 从左往右的和
sumr = 0 # 从右往左的和
# l = len(nums)
lisl = []
lisr = []
for i in range(len(nums)):
suml += nums[i]
lisl.append(suml)
for i in range(len(nums)-1,-1,-1):
sumr += nums[i]
lisr.append(sumr)
# flag = 0
if lisl[0] == lisl[len(nums)-1]:
return 0
elif lisr[0] == lisr[len(nums)-1]:
return len(nums)-1
else:
for j in range(len(nums)):
if lisl[j] == lisr[len(nums)-1-j]:
return j
return -1
一开始感觉自己把两种特殊情况提出来很聪明,结果发现好像题目中这个条件的限制
如果数组有多个中心下标,应该返回 最靠近左边 的那一个
那么当左边的和为0的话,右边如果很多0,就会返回最右边的0
AC了
总结一下自己的思路
再设立一个数组,每一位一次存储原数组nums从右到左的和
遇到相等的就返回j
代码如下
class Solution:
def pivotIndex(self, nums: List[int]) -> int:
suml = 0 # 从左往右的和
sumr = 0 # 从右往左的和
# l = len(nums)
lisl = []
lisr = []
for i in range(len(nums)):
suml += nums[i]
lisl.append(suml)
for i in range(len(nums)-1,-1,-1):
sumr += nums[i]
for j in range(len(nums)):
if lisl[j] == lisr[len(nums)-1-j]:
return j
return -1
但时空复杂度大了些
官方题解:前缀和
题解没给python的,自己AC
对着题解的文字解释,自己写了一个…但是不全对
class Solution:
def pivotIndex(self, nums: List[int]) -> int:
total = 0
sum = 0
for i in range(len(nums)):
total += nums[i]
for i in range(1,len(nums)):
sum +=nums[i-1]
if 2*sum + nums[i] == total:
return i
# if i != len(nums)-1:
# if 2*sum + nums[i+1] == total:
# return i-1
return -1
代码的问题在于下面的循环的i是从1开始遍历
改了个离谱的
class Solution:
def pivotIndex(self, nums: List[int]) -> int:
total = 0
sum = 0
for i in range(len(nums)):
total += nums[i]
for i in range(len(nums)):
sum +=nums[i]
if i != len(nums)-1:
if 2*sum + nums[i+1] == total:
return i+1
return len(nums) - 1
return -1
AC了
既然一开始写的漏了0的情况,那就单独考虑嘛
这样会是啥情况,除了第一个元素,右边的和为0,那么列表的和肯定等于第一个元素
class Solution:
def pivotIndex(self, nums: List[int]) -> int:
total = 0
sum = 0
for i in range(len(nums)):
total += nums[i]
if total == nums[0]:
return 0
for i in range(1,len(nums)):
sum +=nums[i-1]
if 2*sum + nums[i] == total:
return i
return -1
算法通关手册题解
只要改一下我的AC写法一点点就行,就是我是从下标1开始遍历,只要改一处代码的位置,就可以从0开始遍历,无需单独处理
class Solution:
def pivotIndex(self, nums: List[int]) -> int:
total = 0
sum = 0
for i in range(len(nums)):
total += nums[i]
if total == nums[0]:
return 0
for i in range(len(nums)):
if 2*sum + nums[i] == total:
return i
sum +=nums[i]
return -1
刚开始的思路
想到了奇偶校验码
想到了看成连续的数字,110111:十一万零一百一十一
记录0的位置,然后逐个计算0之间的距离,选出最大的,同时 ,数组的第一个元素的前一个元素记为-1以及最后一个元素的后一个记为len(nums)
把这些0所在的位置存在一个数组里面,然后计算每两个之间的差,把这些差存入数组,然后选出里面最大的
初始数组[-1]
遍历的时候一直append 0的下标
最后再append len(nums)
突然发现这样子还不如直接统计1的位置…
因为可能出现连续的0… 而不是说0全是分开的…
下面这个感觉用处不大
class Solution:
def findMaxConsecutiveOnes(self, nums: List[int]) -> int:
maxLen = len(nums)
# zeroNums = [-1,maxLen]
zeorNums = [-1]
for i in range(len(nums)):
if nums[i]==0:
zeroNums.append(i)
zeroNums.append(maxLen)
记录1的位置
思考了十分钟…看答案吧…
官方题解思路
看完思路自己写一遍
class Solution:
def findMaxConsecutiveOnes(self, nums: List[int]) -> int:
maxCount = count = 0
for i in range(len(nums)):
if nums[i] == 1:
count += 1
else:
maxCount = max(maxCount,count)
count = 0
maxCount = max(maxCount,count)
return maxCount
力扣官方题解代码
class Solution:
def findMaxConsecutiveOnes(self, nums: List[int]) -> int:
maxCount = count = 0
for i, num in enumerate(nums):
if num == 1:
count += 1
else:
maxCount = max(maxCount, count)
count = 0
maxCount = max(maxCount, count)
return maxCount
https://www.runoob.com/python3/python3-func-enumerate.html
描述
enumerate()
函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中语法
enumerate(sequence, [start=0])
参数
返回值
实例
seasons = ['Spring', 'Summer', 'Fall', 'Winter']
list(enumerate(seasons)) [(0, 'Spring'), (1, 'Summer'), (2, 'Fall'), (3, 'Winter')]
list(enumerate(seasons, start=1)) # 小标从 1 开始
[(1, 'Spring'), (2, 'Summer'), (3, 'Fall'), (4, 'Winter')]
刚开始思路 暴力解法
哈哈哈,如果没说 请不要使用除法 , 我感觉我一开始还想不到这个方法
无脑求解
class Solution:
def productExceptSelf(self, nums: List[int]) -> List[int]:
answer = []
l = len(nums)
for i in range(l):
ans = 1
for k in range(l):
if k != i:
ans *= nums[k]
answer.append(ans)
return answer
简单的可以,但是复杂的时间复杂度会爆
直接看题解… 摆烂
方法一:左右乘积列表
利用索引左侧所有数字的乘积和右侧所有数字的乘积(即前缀与后缀)相乘得到答案
算法描述
初始化俩空数组L和R。对于给定的索引i,L[i]代表i左侧所有数字的乘积,R[i]代表i右侧所有数字的乘积
用两个循环来填充L和R数组的值
L[0
]应该是1,因为第一个元素的左边没有元素。对于其他元素:L[i] = L[i-1] * nums[i-1]
R[length-1]
应为 1
。length
指的是输入数组的大小。其他元素:R[i] = R[i+1] * nums[i+1]
当 R
和 L
数组填充完成,我们只需要在输入数组上迭代,且索引 i
处的值为:L[i] * R[i]
代码
class Solution:
def productExceptSelf(self, nums: List[int]) -> List[int]:
length = len(nums)
# L 和 R 分别表示左右两侧的乘积列表
L, R, answer = [0]*length, [0]*length, [0]*length
# L[i] 为索引 i 左侧所有元素的乘积
# 对于索引为 '0' 的元素,因为左侧没有元素,所以 L[0] = 1
L[0] = 1
for i in range(1, length):
L[i] = nums[i - 1] * L[i - 1]
# R[i] 为索引 i 右侧所有元素的乘积
# 对于索引为 'length-1' 的元素,因为右侧没有元素,所以 R[length-1] = 1
R[length - 1] = 1
for i in reversed(range(length - 1)):
R[i] = nums[i + 1] * R[i + 1]
# 对于索引 i,除 nums[i] 之外其余各元素的乘积就是左侧所有元素的乘积乘以右侧所有元素的乘积
for i in range(length):
answer[i] = L[i] * R[i]
return answer
复杂度分析
方法二:空间复杂度为O(1)的方法
算法描述
代码
class Solution:
def productExceptSelf(self, nums: List[int]) -> List[int]:
length = len(nums)
answer = [0]*length
# answer[i] 表示索引 i 左侧所有元素的乘积
# 因为索引为 '0' 的元素左侧没有元素, 所以 answer[0] = 1
answer[0] = 1
for i in range(1, length):
answer[i] = nums[i - 1] * answer[i - 1]
# R 为右侧所有元素的乘积
# 刚开始右边没有元素,所以 R = 1
R = 1;
for i in reversed(range(length)):
# 对于索引 i,左边的乘积为 answer[i],右边的乘积为 R
answer[i] = answer[i] * R
# R 需要包含右边所有的乘积,所以计算下一个结果时需要将当前值乘到 R 上
R *= nums[i]
return answer
python reversed
题号 | 标题 | 题解 | 标签 | 难度 |
---|---|---|---|---|
0498 | 对角线遍历 | Python | 数组、矩阵、模拟 | 中等 |
0048 | 旋转图像 | Python | 数组 | 中等 |
0073 | 矩阵置零 | Python | 数组 | 中等 |
0054 | 螺旋矩阵 | Python | 数组 | 中等 |
0059 | 螺旋矩阵 II | Python | 数组、矩阵、模拟 | 中等 |
0289 | 生命游戏 | Python | 数组、矩阵、模拟 | 中等 |