题目:题目链接
解法1(自创:列表特性):
思路:利用Python
列表中的特殊方法pop
和insert
实现尾部元素多次删除后添加到列表首部的方式实现轮转。
缺点:执行用时过长
代码:
class Solution: def rotate(self, nums: List[int], k: int) -> None: """ Do not return anything, modify nums in-place instead. """ for i in range(k): del_elem = nums.pop(-1) nums.insert(0,del_elem) return nums
解法2(切片处理):
思路:利用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 nums[:] = nums[n - k:] + nums[:n - k]
题目:题目链接
解法1(字符串与整型的转化):
思路:将数组元素全部取出转化为字符串,再将字符串进行数据加一处理后改回整型列表形式,避免了多个位置上情况的讨论。
代码
class Solution: def plusOne(self, digits: List[int]) -> List[int]: digits_str = map(str,digits) all_str = "" for i in digits_str: all_str += i all_str = str(int(all_str) + 1) end = list(map(int,list(all_str))) return end
解法2(官方解法:多情况讨论)
思路:当我们对数组digits加一时,我们只需要关注digits的末尾出现了多少个9即可。我们可以考虑如下的三种情况:如果digits的末尾没有9,例如1,2,3
,那么我们直接将末尾的数加一,得到1,2,4
并返回;如果digits的末尾有若干个9,例如1,2,3,9,9
,那么我们只需要找出从末尾开始的第一个不为9的元素,即3,将该元素加一,得到1,2,4,9,9
。随后将末尾的9全部置零,得到1,2,4,0,0
并返回。如果digits的所有元素都是9,例如9,9,9,9,9
,那么答案为1,0,0,0,0,0
。我们只需要构造一个长度比digits多1的新数组,将首元素置为1,其余元素置为0即可。
代码:
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 # digits 中所有的元素均为 9 return [1] + [0] * n
题目:题目链接
解法1(区间和):
思路:看代码
代码:
class Solution: def pivotIndex(self, nums: List[int]) -> int: for i in range(len(nums)): if ((i == 0) and (sum(nums[i+1:]) == 0)): return i if ((i == (len(nums)-1)) and (sum(nums[0:i]) == 0)): return i if sum(nums[0:i]) == sum(nums[i+1:]): return i return -1
解法2(前缀和):
思路:
代码:
class Solution(object): def pivotIndex(self, nums): """ :type nums: List[int] :rtype: int """ N = len(nums) sums_ = sum(nums) preSum = 0 for i in range(N): if preSum == sums_ - preSum - nums[i]: return i preSum += nums[i] return -1
题目:题目链接
解法1(自创):
思路:重新取一列表对连续1的个数进行存储,此时即使遇到不为1的数存储到0也没有关系,因为最大连续1最小就是0。
代码:
class Solution: def findMaxConsecutiveOnes(self, nums: List[int]) -> int: lianxu_one = [] count = 0 for i in range(len(nums)): if nums[i] == 1: count += 1 if (nums[i] != 1) or (i == (len(nums)-1)): lianxu_one.append(count) count = 0 return max(lianxu_one)
解法2(解法1优化):
思路:一次遍历,遇到1让cur加一,遇到0则更新cur和ans,速度最优。
代码:
class Solution: def findMaxConsecutiveOnes(self, nums: List[int]) -> int: cur, ans = 0, 0 for i in range(len(nums)): if nums[i] == 1: cur += 1 else: ans = max(ans, cur) cur = 0 return max(ans, cur)
题目:题目链接
解法1(O(n)):
思路:LeetCode官方解答
代码:
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
解法2(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
题目:题目链接
解法(O(n^2)):
思路:反转矩阵,然后对称元素替换即可
代码:
class Solution: def rotate(self, matrix: List[List[int]]) -> None: """ Do not return anything, modify matrix in-place instead. """ matrix.reverse() for i in range(len(matrix)): for j in range(i+1, len(matrix[i])): matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j] return matrix
题目:题目链接
解法1(O(mn)):
思路:首先创建一个新列表,存放原列表中元素为0的行索引与列索引。然后调用新列表,将行索引和列索引上的元素全部置零。
代码:
class Solution: def setZeroes(self, matrix: List[List[int]]) -> None: """ Do not return anything, modify matrix in-place instead. """ li = [] for i in range(len(matrix)): for j in range(len(matrix[i])): if matrix[i][j] == 0: li.append([i,j]) for i in li: matrix[i[0]][:] = [0 for i in range(len(matrix[i[0]]))] for j in range(len(matrix)): matrix[j][i[1]] = 0 return matrix
解法2(O(mn)/O(1)):
思路:
代码:
class Solution: def setZeroes(self, matrix: List[List[int]]) -> None: m, n = len(matrix), len(matrix[0]) flag_col0 = any(matrix[i][0] == 0 for i in range(m)) flag_row0 = any(matrix[0][j] == 0 for j in range(n)) for i in range(1, m): for j in range(1, n): if matrix[i][j] == 0: matrix[i][0] = matrix[0][j] = 0 for i in range(1, m): for j in range(1, n): if matrix[i][0] == 0 or matrix[0][j] == 0: matrix[i][j] = 0 if flag_col0: for i in range(m): matrix[i][0] = 0 if flag_row0: for j in range(n): matrix[0][j] = 0
题目:题目链接
解法:
思路(转自ikaruga):
每一趟对角线中元素的坐标(x, y)相加的和是递增的。
第一趟:1 的坐标(0, 0)。x + y == 0。
第二趟:2 的坐标(1, 0),4 的坐标(0, 1)。x + y == 1。
第三趟:7 的坐标(0, 2), 5 的坐标(1, 1),3 的坐标(2, 0)。第三趟 x + y == 2。
第四趟:……
每一趟都是 x 或 y 其中一个从大到小(每次-1),另一个从小到大(每次+1)。
第二趟:2 的坐标(1, 0),4 的坐标(0, 1)。x 每次-1,y 每次+1。
第三趟:7 的坐标(0, 2), 5 的坐标(1, 1),3 的坐标(2, 0)。x 每次 +1,y 每次 -1。
确定初始值。例如这一趟是 x 从大到小, x 尽量取最大,当初始值超过 x 的上限时,不足的部分加到 y 上面。
第二趟:2 的坐标(1, 0),4 的坐标(0, 1)。x + y == 1,x 初始值取 1,y 取 0。
第四趟:6 的坐标(2, 1),8 的坐标(1, 2)。x + y == 3,x 初始值取 2,剩下的加到 y上,y 取 1。
确定结束值。例如这一趟是 x 从大到小,这一趟结束的判断是, x 减到 0 或者 y 加到上限。
第二趟:2 的坐标(1, 0),4 的坐标(0, 1)。x 减到 0 为止。
第四趟:6 的坐标(2, 1),8 的坐标(1, 2)。x 虽然才减到 1,但是 y 已经加到上限了。
这一趟是 x 从大到小,那么下一趟是 y 从大到小,循环进行。 并且方向相反时,逻辑处理是一样的,除了x,y和他们各自的上限值是相反的。
x 从大到小,第二趟:2 的坐标(1, 0),4 的坐标(0, 1)。x + y == 1,x 初始值取 1,y 取 0。结束值 x 减到 0 为止。
x 从小到大,第三趟:7 的坐标(0, 2),5 的坐标(1, 1),3 的坐标(2, 0)。x + y == 2,y 初始值取 2,x 取 0。结束值 y 减到 0 为止。
代码:
class Solution: def findDiagonalOrder(self, mat: List[List[int]]) -> List[int]: m=len(mat) n=len(mat[0]) s=0 ans=[] while s<m+n: #第1,3,5趟 x1=s if s<m else m-1 y1=s-x1 while x1>=0 and y1<n: ans.append(mat[x1][y1]) x1-=1 y1+=1 s+=1 if s>=m+n: break #第2,4,6趟 y2=s if s<n else n-1 x2=s-y2 while y2>=0 and x2<m: ans.append(mat[x2][y2]) x2+=1 y2-=1 s+=1 return ans
题目:题目链接
解法(O(n)):
思路:首先定义与杨辉三角相同规模的全为1的列表,然后利用生成的列表组成新列表。
代码:
class Solution: def generate(self, numRows: int) -> List[List[int]]: start_matrix = [] for i in range(numRows): start_matrix.append([1 for i in range(i+1)] ) for i in range(2,numRows): for j in range(1,i): start_matrix[i][j] = start_matrix[i-1][j-1]+start_matrix[i-1][j] return start_matrix
题目:题目链接
解法:
思想:和118思想一样,只不过固定生成行数之后输出最后一行即可。
代码:
class Solution: def getRow(self, rowIndex: int) -> List[int]: start_matrix = [] for i in range(rowIndex+1): start_matrix.append([1 for i in range(i+1)] ) for i in range(2,rowIndex+1): for j in range(1,i): start_matrix[i][j] = start_matrix[i-1][j-1]+start_matrix[i-1][j] return start_matrix[-1]
题目:题目链接
解法:
思想:同面试题01.08解法2
代码:
class Solution: def setZeroes(self, matrix: List[List[int]]) -> None: m, n = len(matrix), len(matrix[0]) flag_col0 = any(matrix[i][0] == 0 for i in range(m)) flag_row0 = any(matrix[0][j] == 0 for j in range(n)) for i in range(1, m): for j in range(1, n): if matrix[i][j] == 0: matrix[i][0] = matrix[0][j] = 0 for i in range(1, m): for j in range(1, n): if matrix[i][0] == 0 or matrix[0][j] == 0: matrix[i][j] = 0 if flag_col0: for i in range(m): matrix[i][0] = 0 if flag_row0: for j in range(n): matrix[0][j] = 0
题目:题目链接
思路(见注释)和解法1:
class Solution: def spiralOrder(self, matrix: List[List[int]]) -> List[int]: if not matrix:return [] x=y=0 # 矩阵元素位置初始化 res = [] # 初始化,存储遍历后的矩阵元素 dx = [ 0, 1, 0,-1] # 方向:右,下,左,上 dy = [ 1, 0,-1, 0] # 注:与通常平面坐标系 记号 不同 di = 0 # 初始化方向变量 visited = set() # 初始化集合,存储已走过的坐标 m,n = len(matrix),len(matrix[0]) # 矩阵的行列 for i in range(m*n): res.append(matrix[x][y]) # 存储遍历矩阵过的元素 visited.add((x,y)) # 存储遍历过的坐标 tx,ty = x+dx[di],y+dy[di] # 先记录下一步坐标,用于判断下一步怎么走 if 0<=tx<m and 0<=ty<n and (tx,ty) not in visited: # 判断坐标是否需变向,且没有遍历过 x,y = tx,ty else: di = (di+1)%4 # 改变方向,右下左上为一圈,防止方向坐标越界 x,y = x + dx[di],y+dy[di] # 下一步坐标 return res
解法2:
思路:
代码:
class Solution(object): def spiralOrder(self, matrix): """ :type matrix: List[List[int]] :rtype: List[int] """ if not matrix or not matrix[0]: return [] M, N = len(matrix), len(matrix[0]) left, right, up, down = 0, N - 1, 0, M - 1 res = [] x, y = 0, 0 dirs = [(0, 1), (1, 0), (0, -1), (-1, 0)] cur_d = 0 while len(res) != M * N: res.append(matrix[x][y]) if cur_d == 0 and y == right: cur_d += 1 up += 1 elif cur_d == 1 and x == down: cur_d += 1 right -= 1 elif cur_d == 2 and y == left: cur_d += 1 down -= 1 elif cur_d == 3 and x == up: cur_d += 1 left += 1 cur_d %= 4 x += dirs[cur_d][0] y += dirs[cur_d][1] return res
题目:题目链接
解法:
代码:
class Solution: def gameOfLife(self, board: List[List[int]]) -> None: """ Do not return anything, modify board in-place instead. """ neighbors = [(1,0), (1,-1), (0,-1), (-1,-1), (-1,0), (-1,1), (0,1), (1,1)] rows = len(board) cols = len(board[0]) # 从原数组复制一份到 copy_board 中 copy_board = [[board[row][col] for col in range(cols)] for row in range(rows)] # 遍历面板每一个格子里的细胞 for row in range(rows): for col in range(cols): # 对于每一个细胞统计其八个相邻位置里的活细胞数量 live_neighbors = 0 for neighbor in neighbors: r = (row + neighbor[0]) c = (col + neighbor[1]) # 查看相邻的细胞是否是活细胞 if (r < rows and r >= 0) and (c < cols and c >= 0) and (copy_board[r][c] == 1): live_neighbors += 1 # 规则 1 或规则 3 if copy_board[row][col] == 1 and (live_neighbors < 2 or live_neighbors > 3): board[row][col] = 0 # 规则 4 if copy_board[row][col] == 0 and live_neighbors == 3: board[row][col] = 1