入坑力扣,希望可以经常练一练,然后记录一下,更新。
所有一级标题的前缀为:leetcode-cn.com/problems
/container-with-most-water
第一次使用了暴力O(n^2)的方法,直接超出限制,后来改为O(n)。
Python
class Solution: def maxArea(self, height: List[int]) -> int: current_max_area = 0 left = 0 right = len(height)-1 while right>left: area = (right-left)*min(height[left], height[right]) if area > current_max_area: current_max_area = area if height[left] > height[right]: right -= 1 else: left += 1 return current_max_area
C
int maxArea(int* height, int heightSize){ int current_max_area = 0; int area; int left = 0; int right = heightSize-1; while (right > left){ if (height[left] > height[right]){ area = (right-left)*height[right]; right -= 1; }else{ area = (right-left)*height[left]; left += 1; } if (area > current_max_area){ current_max_area = area; } } return current_max_area; }
大佬ChengMing评论:这里用到了动态规划,基本的表达式: area = min(height[i], height[j]) * (j - i),使用两个指针,值小的指针向内移动,这样就减小了搜索空间。因为面积取决于指针的距离与值小的值乘积,如果值大的值向内移动,距离一定减小,而求面积的另外一个乘数一定小于等于值小的值,因此面积一定减小,而我们要求最大的面积,因此值大的指针不动,而值小的指针向内移动遍历。
/valid-sudoku/submissions/
class Solution: def isValidSudoku(self, board: List[List[str]]) -> bool: rows = [[] for _ in range(0,9)] columns = [[] for _ in range(0,9)] squares = [[] for _ in range(0,9)] for i in range(0,9): for j in range(0,9): if board[i][j] != '.': if board[i][j] in rows[i]: return False else: rows[i].append(board[i][j]) if board[i][j] in columns[j]: return False else: columns[j].append(board[i][j]) k1 = i//3 k2 = j//3 k = k1 + k2 * 3 if board[i][j] in squares[k]: return False else: squares[k].append(board[i][j]) return True
思路一:
- 对于每一行,检验是否有重复元素;
- 对于每一列,检验是否有重复元素;
- 对于每一个方格,检验是否有重复元素。
思路二(采用):
- 对每一行、每一列、每个方格建立一个列表,存储已经出现过的元素;
- 对矩阵中的各个元素依次扫描,查看其是否已在对应的行、列、方格中出现过;
- 如已曾出现返回false,如未出现将其加入。
/sudoku-solver
class Solution: def solveSudoku(self, board): """ :type board: List[List[str]] :rtype: void Do not return anything, modify board in-place instead. """ def is_valid(i, j, s): k_row = i//3 k_col = j//3 b_square = [] for k in range(0,3): b_square += board[3*k_row:3*k_row+3][k][3*k_col:3*k_col+3] if (s in board[i]) or (s in [b[j] for b in board]) or (s in b_square): return False return True def is_possible(position): if position == 81: return True i, j = position//9, position % 9 if board[i][j] != '.': return is_possible(position+1) for k in range(0,9): s = str(k+1) if is_valid(i, j, s): board[i][j] = s if is_possible(position+1): return True else: board[i][j] = '.' return False is_possible(0)
这个真写不出,以上代码参考自xyz,
解数独思路:
对于所有未填充的格子,从1~9中选择数字,依次尝试填充,如果发现重复了,那么擦除,退回上一步,直到把整个数组填充完成。
重点在于这个退回过程的实现,实际上也就是所说的回溯。
/jump-game
解题思路:从后向前遍历元素,对于最后一个元素a,判断是否有前面的元素b可以跳到它。如果有,则问题转换为是否可以从开头跳到元素b,截断后面的元素;如果没有,输出False。
class Solution: def whichCanJump(self, nums, index): for i in range(0,index): j=index-i-1 if nums[j]+j>=index: return j return index def canJump(self, nums: List[int]) -> bool: l = len(nums) current = l-1 while current!=0: lastStep = self.whichCanJump(nums,current) if lastStep==current: return False else: current = lastStep return True
/spiral-matrix
思路:记录上下左右边界所在的位置,依次循环输出上、右、下、左的元素,但是遇到一些错误,因此做了一些修正。
class Solution: def spiralOrder(self, matrix: List[List[int]]) -> List[int]: data=[] up=0 left=0 down=len(matrix)-1 right=len(matrix[0])-1 while True: data+=matrix[up][left:right] data+=[matrix[i][right] for i in range(up,down)] data+=matrix[down][right:left:-1] data+=[matrix[i][left] for i in range(down,up,-1)] up+=1 down-=1 left+=1 right-=1 if up>down: break if left>right: break #弥补第一种情况[[1,2,3],[4,5,6],[7,8,9]] if len(data)<len(matrix)*len(matrix[0]): data.append(matrix[up-1][left-1]) #弥补第二种情况[[1,2,3,4,5,6,7,8,9]] while len(data)>len(matrix)*len(matrix[0]): data.pop() return data