Leetcode刷题笔记

目录

一、双指针

二、排序

三、贪心算法

四、二分查找

五、分治算法

六、搜索(DFS&BFS)

七、动态规划

八、递归

九、回溯

十、查并集

十一、滑动窗口

十二、记忆化搜索

一、双指针

题号:86、167、209

【典型题目】给定一个已按照 升序排列 的整数数组 numbers ,请你从数组中找出两个数满足相加之和等于目标数 target

 1 class Solution:
 2 
 3     def twoSum(self, numbers: List[int], target: int) -> List[int]:
 4 
 5         i = 0
 6 
 7         j = len(numbers) - 1
 8 
 9         while i < j:
10 
11             if target - numbers[j] == numbers[i]:
12 
13                 return [i + 1, j + 1]
14 
15             elif numbers[i] + numbers[j] > target:
16 
17                 j -= 1
18 
19             else:
20 
21                 i += 1
22 
23         return []

二、排序

题号:207、210

1. 转换成堆,堆 :时间复杂度 O(NlogK),空间复杂度 O(K)。

【典型题目】在某个集合中找出最大或最小的N个元素

 1 import heapq
 2 
 3 >>> nums=[1,8,2,23,7,-4,18,23,42,37,2]
 4 
 5 >>> print(heapq.nlargest(3,nums))
 6 
 7 [42, 37, 23]
 8 
 9 >>> print(heapq.nsmallest(3,nums))
10 
11 [-4, 1, 2]

【典型题目】如果正在寻找最大或者最小的N个元素,且同集合中元素的总数目相比,N很小,那么下面这些函数就可以提供更好的性能。

这些函数首先会在底层将数据转化成列表,且元素会以堆得顺序排列。例如:

 1 >>> nums=[1,8,2,23,7,-4,18,23,42,37,2]
 2 
 3 >>> import heapq
 4 
 5 >>> heap=list(nums)
 6 
 7 >>> heapq.heapify(heap)#将列表原地转换成堆
 8 
 9 >>> heap
10 
11 [-4, 2, 1, 23, 7, 2, 18, 23, 42, 37, 8]

2. 排序 :时间复杂度 O(NlogN),空间复杂度 O(1)

3. 快速选择 :时间复杂度 O(N),空间复杂度 O(1)

4. 拓扑排序:是专门应用于有向图的算法,BFS 的写法就叫「拓扑排序」,这里还用到了贪心算法的思想,贪的点是:当前让入度为 0 的那些结点入队

三、贪心算法

题号:322、1217、55

四、二分查找

题号:704、35、162、74

【典型题目】给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1

 1 class Solution:
 2 
 3     def search(self, nums: List[int], target: int) -> int:
 4 
 5         left, right = 0, len(nums)-1
 6 
 7         while left <= right:
 8 
 9             mid = left + (right - left) // 2
10 
11             if nums[mid] > target:
12 
13                 right = mid - 1
14 
15             elif nums[mid] < target:
16 
17                 left = mid + 1
18 
19             elif nums[mid] == target:
20 
21                 return mid
22 
23         return -1

【典型题目】编写一个高效的算法来判断 m x n 矩阵中,是否存在一个目标值

 1 class Solution:
 2 
 3     def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
 4 
 5         n , m = len(matrix) , len(matrix[0])
 6 
 7         if m == 0 or n == 0 :return False
 8 
 9         l , r = 0 , m * n - 1
10 
11         while (l <= r):
12 
13             mid = (l + r) // 2
14 
15             if(matrix[mid // m][mid % m] > target):
16 
17                 r = mid - 1
18 
19             elif(matrix[mid // m][mid % m] < target):
20 
21                 l = mid + 1
22 
23             else:
24 
25                 return True
26 
27         return False                

五、分治算法

题号:169、53

【典型题目】给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

注:便捷算法

 1 class Solution:
 2 
 3     def maxSubArray(self, nums: List[int]) -> int:
 4 
 5         res = nums[0]
 6 
 7         sum = 0
 8 
 9         for num in nums:
10 
11             if sum > 0 :
12 
13                 sum += num
14 
15             else:
16 
17                 sum = num
18 
19             res = max(res,sum)
20 
21         return res

六、搜索(DFS&BFS)

1. DFS 题号:938、78、200

【典型题目】给定二叉搜索树的根结点 root,返回值位于范围 [low, high] 之间的所有结点的值的和。

 1 class Solution:
 2 
 3     def rangeSumBST(self, root: TreeNode, low: int, high: int) -> int:
 4 
 5         if root==None:
 6 
 7             return 0
 8 
 9         ans_left = self.rangeSumBST(root.left, low, high)
10 
11         ans_right = self.rangeSumBST(root.right, low, high)
12 
13         rootval = root.val if low<=root.val<=high else 0
14 
15         return ans_left + ans_right + rootval

【典型题目】给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。

方法一==>DFS:

 1 class Solution:
 2 
 3     def dfs(self, res, nums, cur, index):
 4 
 5         if index >= len(nums):
 6 
 7             res.append(cur.copy())  # 注意这里要用copy 要不然cur的改变会影响到res里的cur
 8 
 9             return
10 
11         # 下面有两个dfs 表示每个状态有两个子状态可供选择
12 
13         # 每个index前后保证状态不变
14 
15         cur.append(nums[index])
16 
17         self.dfs(res, nums, cur, index + 1)
18 
19         cur.pop()
20 
21         self.dfs(res, nums, cur, index + 1)
22 
23         
24 
25     def subsets(self, nums: List[int]) -> List[List[int]]:
26 
27         # 本题定义状态为(cur, index)
28 
29         res = []
30 
31         self.dfs(res, nums, [], 0)
32 
33         return res

方法二==>递归:

1 class Solution(object):
2 
3     def subsets(self, nums):
4 
5         if nums ==[]:
6 
7             return [[]]
8 
9         return self.subsets(nums[:-1]) + [i+[nums[-1]] for i in self.subsets(nums[:-1])]

【典型题目】岛屿数量

给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。

岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。

此外,你可以假设该网格的四条边均被水包围。

方法一==>DFS

 1 class Solution:
 2 
 3     def numIslands(self, grid: List[List[str]]) -> int:
 4 
 5         if not grid: return 0
 6 
 7         
 8 
 9         count = 0
10 
11         for i in range(len(grid)):
12 
13             for j in range(len(grid[0])):
14 
15                 if grid[i][j] == '1':
16 
17                     self.dfs(grid, i, j)
18 
19                     count += 1
20 
21                     
22 
23         return count
24 
25     
26 
27     def dfs(self, grid, i, j):
28 
29         if i < 0 or j < 0 or i >= len(grid) or j >= len(grid[0]) or grid[i][j] != '1':
30 
31             return
32 
33         grid[i][j] = '0'
34 
35         self.dfs(grid, i + 1, j)
36 
37         self.dfs(grid, i - 1, j)
38 
39         self.dfs(grid, i, j + 1)
40 
41         self.dfs(grid, i, j - 1)

方法二==>BFS

 1 class Solution:
 2 
 3     def numIslands(self, grid: List[List[str]]) -> int:
 4 
 5         count = 0
 6 
 7         for row in range(len(grid)):
 8 
 9             for col in range(len(grid[0])):
10 
11                 if grid[row][col] == '1':  # 发现陆地
12 
13                     count += 1  # 结果加1
14 
15                     grid[row][col] = '0'  # 将其转为 ‘0’ 代表已经访问过
16 
17                     # 对发现的陆地进行扩张即执行 BFS,将与其相邻的陆地都标记为已访问
18 
19                     # 下面还是经典的 BFS 模板
20 
21                     land_positions = collections.deque()
22 
23                     land_positions.append([row, col])
24 
25                     while len(land_positions) > 0:
26 
27                         x, y = land_positions.popleft()
28 
29                         for new_x, new_y in [[x, y + 1], [x, y - 1], [x + 1, y], [x - 1, y]]:  # 进行四个方向的扩张
30 
31                             # 判断有效性
32 
33                             if 0 <= new_x < len(grid) and 0 <= new_y < len(grid[0]) and grid[new_x][new_y] == '1':
34 
35                                 grid[new_x][new_y] = '0'  # 因为可由 BFS 访问到,代表同属一块岛,将其置 ‘0’ 代表已访问过
36 
37                                 land_positions.append([new_x, new_y])
38 
39         return count

2. BFS 题号:102、107、200

【典型题目】102题:给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。

当遍历到新的一层的时候(也就是depth>=res数组的长度的时候),就往res里append一个空列表用于存储新的一层的结点值

同时往该结点对应那一层的列表里(res[depth])append结点的值对该结点的左子节点和右子节点重复以上工作,由于是从上到下存储的各层元素,所以最后需要倒转一下列表。

DFS

 1 class Solution:
 2 
 3     def levelOrderBottom(self, root: TreeNode) -> List[List[int]]:
 4 
 5         res = []
 6 
 7         def dfs(root, depth):
 8 
 9             if not root:
10 
11                 return
12 
13             if len(res)<depth+1:
14 
15                 res.append([])
16 
17             res[depth].append(root.val)
18 
19             dfs(root.left, depth+1)
20 
21             dfs(root.right, depth+1)
22 
23         dfs(root,0)
24 
25         return res[::-1]

七、动态规划

题号:62、322、1143、509、121、70、279、22

【典型题目】给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。你可以认为每种硬币的数量是无限的。

 1 class Solution:
 2 
 3     def coinChange(self, coins: List[int], amount: int) -> int:
 4 
 5         dp = [float('inf')] * (amount + 1)
 6 
 7         dp[0] = 0
 8 
 9  
10 
11         for coin in coins:
12 
13             for i in range(coin, amount + 1):
14 
15                 dp[i] = min(dp[i], 1 + dp[i - coin])
16 
17         
18 
19         return dp[amount] if dp[amount] != float('inf') else -1

【典型题目】给定两个字符串 text1 和 text2,返回这两个字符串的最长公共子序列的长度。

一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。

例如,"ace" 是 "abcde" 的子序列,但 "aec" 不是 "abcde" 的子序列。两个字符串的「公共子序列」是这两个字符串所共同拥有的子序列。

若这两个字符串没有公共子序列,则返回 0。

 1 class Solution(object):
 2 
 3     def longestCommonSubsequence(self, text1, text2):
 4 
 5         """
 6 
 7         :type text1: str
 8 
 9         :type text2: str
10 
11         :rtype: int
12 
13         """
14 
15         if not text1 or not text2:
16 
17             return 0
18 
19         #base case
20 
21         n = len(text1)
22 
23         m = len(text2)
24 
25         dp = [[0 for x in range(n+1)] for y in range(m+1)]
26 
27         for i in range(1,m+1):
28 
29             for j in range(1,n+1):
30 
31                 if text1[j-1] == text2[i-1]:
32 
33                     dp[i][j] = dp[i-1][j-1] + 1
34 
35                 else:
36 
37                     dp[i][j] = max(dp[i-1][j], dp[i][j-1])
38 
39         return dp[m][n]

八、递归

题号:509、206、344、687

【典型题目】斐波那契数列

方法一==>纯递归

1 class Solution:
2 
3     def fib(self, n: int) -> int:
4 
5         if n == 0 or n == 1 : return n
6 
7         else:
8 
9             return self.fib(n - 1) + self.fib( n - 2)

方法二==>递归+记忆法(数组)            

 1 class Solution:
 2 
 3     def fib(self, n: int) -> int:
 4 
 5         memo=[0,1]
 6 
 7         i=2
 8 
 9         if n<2:
10 
11             return memo[n]        
12 
13         while i<=n:
14 
15             memo.append(memo[i-1]+memo[i-2])
16 
17             i+=1
18 
19         return memo[-1]

方法三==>动态规划

 1 class Solution:
 2 
 3     def fib(self, n: int) -> int:
 4 
 5         if n == 0:
 6 
 7             return 0
 8 
 9         if n <= 2:
10 
11             return 1
12 
13         first = 1
14 
15         second = 1
16 
17         for i in range(3, n+1):
18 
19             first, second = second, first + second
20 
21         return second

【典型题目】反转一个链表

 1 class Solution:
 2 
 3     def reverseList(self, head: ListNode) -> ListNode:
 4 
 5         if not head or head.next == None: return head
 6 
 7         res = self.reverseList(head.next)
 8 
 9         head.next.next = head
10 
11         head.next = None
12 
13         return res

【典型题目】反转字符串

双指针法

 1 class Solution:
 2 
 3     def reverseString(self, s: List[str]) -> None:
 4 
 5         """
 6 
 7         Do not return anything, modify s in-place instead.
 8 
 9         """
10 
11         # double pointer
12 
13         i,j = 0,len(s)-1
14 
15         while i<j:
16 
17             s[i],s[j] = s[j],s[i]
18 
19             i+=1;j-=1

九、回溯

题号:22、78、77、46

【典型题目】给定两个整数 n 和 k,返回 1 ... n 中所有可能的 k 个数的组合。

 1 class Solution:
 2 
 3     def combine(self, n: int, k: int) -> List[List[int]]:
 4 
 5         res = []
 6 
 7         def backtrack(i, k, tmp):
 8 
 9             if k == 0:
10 
11                 res.append(tmp)
12 
13                 return
14 
15             for j in range(i, n + 1):
16 
17                 backtrack(j+1, k-1, tmp + [j])
18 
19         backtrack(1, k, [])
20 
21         return res

十、并查集

题号:200、547、721

十一、滑动窗口

题号:209、1456

十二、记忆化搜索

题号:509、322

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值