【手把手带你刷Leetcode力扣】算法

1.算法 - 双指针

  • 普通双指针:两个指针往同一个方向移动
  • 对撞双指针:两个指针面对面移动(有序数列)
  • 快慢双指针:慢指针+快指针(环形链表)

141.环形链表

class Solution:
	# Time Complexity: O(N)
	# Space Complexity: O(1)
	def hasCycle(self, head: ListNode) -> bool:
		if head is None:
			return False
		slow = head
		fast = head
		while fast is not None and fast.next is not None:
			fast = fast.next.next
			slow = slow.next
			if slow == fast:
				return True
		
		retrun False

881.救生艇

class Solution:
	# Time Complexity: O(NlogN)
	# Space Complexity: O(1)
	def numRescueBoats(self, people: List[int], limit: int) -> int:
		if people is None or len(people) == 0:
			retrun 0
		people.sort()
		i = 0
		j = len(people) - 1
		res = 0
		while (i <= j):
			if people[i]+people[j] <= limit:
				i = i + 1
			j = j - 1
			res = res + 1
		return res

2.算法 - 二分查找法

有序数列

O(logN)

m = l + (r-l)//2
避免超过int型范围

  1. 二分查找

常规法:

class Solution(object):
	# Time Complexity: O(N)
	# Space Complexity: O(1)
	def search(self, nums, target):
		for i in range(len(nums)):
			if nums[i] == target:
				return i
		return -1

二分查找法:

class Solution(object):
	# Time Complexity: O(logN)
	# Space Complexity: O(1)
	def search(self, nums, target):
		if nums == None or len(nums) == 0:
			return -1
		left, right = 0, len(nums)-1
		while (left<=right):
			mid = left + (right - left)//2
			if nums[mid] == target:
				return mid
			elif nums[mid] > target:
				right = mid - 1
			else:
				left = mid + 1
		return -1
  1. 搜索插入位置

常规法:

class Solution(object):
	# Time Complexity: O(N)
	# Space Complexity: O(1)
	def searchInsert(self, nums, target):
		if nums == None or len(nums) == 0:
			return 0
		prev = -1
		for i in range(len(nums)):
			if nums[i] == target:
				return i
			elif num[i] < target:
				prev = i
			else:
				return prev+1
		return prev+1

二分查找法:

class Solution(object):
	# Time Complexity: O(logN)
	# Space Complexity: O(1)
	def searchInsert(self, nums, target):
		if nums == None or len(nums) == 0:
			return 0
		left, right = 0, len(nums)
		while (left<right):
			mid = left + (right - left)/2
			if nums[mid] == target:
				return mid
			elif nums[mid] > target:
				right = mid
			else:
				left = mid + 1
		return left
  1. 寻找峰值
class Solution(object):
	# Time Complexity: O(logN)
	# Space Complexity: O(1)
	def findPeakElement(self, nums: List[int]) -> int:
		if nums is None or len(nums) == 0:
			return -1
		l = 0
		r = len(nums) - 1
		while l < r:
			mid = l + (r-l)//2
			if nums[mid] > nums[mid+1]:
				r = mid
			else:
				l = mid + 1
		return l
  1. 搜索二维矩阵
class Solution(object):
	# Time Complexity: O(logN)
	# Space Complexity: O(1)
	def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
		if matrix is None or len(matrix) == 0:
			return False
		row = len(matrix)
		col = len(matrix[0])
		l = 0
		r = row * col - 1
		while l <= r:
			m = l + (r-l)//2
			element = matrix[m//col][m%col]
			if element == target:
				return True
			elif element > target:
				r = m - 1
			else:
				l = m + 1
		return False

3.算法 - 滑动窗口法

目的:减少while循环

数组中的定长问题

  1. 长度最小的子数组

暴力法:

class Solution(object):
	# Time Complexity: O(N^2)
	# Space Complexity: O(1)
	def minSubArrayLen(self, s: int, nums: List[int]) -> int:
		if nums is None or len(nums) == 0:
			return 0
		size = 1
		while size <= len(nums):
			for i in range(len(nums)-size+1):
				total = sum(nums[i: i+size])
				if total >= s:
					return size
			size += 1
		return 0	

滑动窗口法(双指针法):

class Solution(object):
	# Time Complexity: O(N)
	# Space Complexity: O(1)
	def minSubArrayLen(self, s: int, nums: List[int]) -> int:
		if nums is None or len(nums) == 0:
			return 0
		result = len(nums) + 1
		total = 0
		i, j = 0, 0
		while j < len(nums):
			total += num[j]
			j += 1
			while total >= s:
				result = min(result, j - i)
				total -= nums[i]
				i += 1
			return 0 if result == len(nums)+1 else result

  1. 定长子串中元音的最大数目
class Solution(object):
	# Time Complexity: O(N)
	# Space Complexity: O(1)
	def maxVowels(self, s: str, k: int) -> int:
		if s is None or len(s) == 0 or len(s) < k:
			return 0
		hashset = set(['a', 'o', 'e', 'i', 'u'])
		res = 0
		count = 0
		for i in range(0, k):
			if s[i] in hashset:
				count = count + 1
		res = max(res, count)
		for i in range(k, len(s)):
			out = s[i-k]
			inc = s[i]
			if out in hashset:
				count = count - 1
			if inc in hashset:
				count = count + 1
			res = max(res, count)
		return res
			

4.算法 - 递归法

函数直接或间接调用自己

  • 递归
  • 回溯
  • 深度优先搜索
  • 分治法

4个要素

  • 接受的参数
  • 返回值
  • 终止的条件
  • 递归拆解:如何递归下一层
  1. 斐波那契数
class Solution(object):
	# Time Complexity: O(N)
	# Space Complexity: O(N)
	def fib(self, N: int) -> int:
		if N < 2:
			return 0 if N == 0 else 1
		m = self.fib(N-1) + self.fib(N-2)
		return m
  1. 反转链表

迭代法:

class Solution(object):
	# Time Complexity: O(N)
	# Space Complexity: O(1)
	def reverseList(self, head: ListNode) -> ListNode:
		dummy = ListNode()
		dummy.next = head
		while (head != None and head.next != None):
			dummy_next = dummy.next
			temp = head.next
			dummy.next, head.next, temp.next = temp, temp.next, dummy_next
		return dummy.next

递归法:

class Solution(object):
	# Time Complexity: O(N)
	# Space Complexity: O(N)
	def reverseList(self, head: ListNode) -> ListNode:
		if not head or not head.next:
			return head
		p = self.reverseList(head.next)
		head.next.next = head
		head.next = None
		return p
  1. 反转字符串
class Solution(object):
	# Time Complexity: O(N/2)
	# Space Complexity: O(N/2)
	def reverseString(self, s: List[str]) -> None:
		self.recursion(s, 0, len(s)-1)
	
	def recursion(self, s, left, right):
		if left >= right:
			return
		self.recursion(s, left+1, right-1)
		s[left], s[right] = s[right], s[left]

5.算法 - 分治法

大问题切割成一个个小问题

用到递归,自己调用自己

  1. 多数元素
class Solution(object):
	# Time Complexity: O(NlogN)
	# Space Complexity: O(logN)
		def majorityElement(self, nums: List[int] -> int:
			return self.getMajority(nums, 0, len(nums)-1)
		
		def getMajority(self, nums, left, right):
			if left == right:
				return nums[left]
			
			mid = left + (right - left) // 2
			leftMajority = self.getMajority(nums, left, mid)
			rightMajority = self.getMajority(nums, mid+1, right)
			if leftMajority == rightMajority:
				return leftMajority
			
			leftCount = 0
			rightCount = 0
			for i in range(left, right+1):
				if nums[i] == leftMajority:
					leftCount += 1
				elif nums[i] == rightMajority:
					right += 1
			
			return leftMajority if leftCount > rightCount else rightMajority
  1. 最大序列和
class Solution(object):
	# Time Complexity: O(N)
	# Space Complexity: O(logN)
	def maxSubArray(self, nums: List[int]) -> int:
		return self.getMax(nums, 0, len(nums)-1)
	
	def getMax(self, nums, l, r):
		if l == r:
			return nums[l]
		mid = l + (r-l)//2
		leftSum = self.getMax(nums, l, mid)
		rightSum = self.getMax(nums, mid+1, r)
		crossSum = self.crossSum(nums, l, r)
		return max(leftSum, rightSum, crossSum)
	
	def crossSum(self, nums, l, r):
		mid l + (r-l)//2
		# from mid to leftmost
		leftSum = nums[mid]
		leftMax = leftSum
		for i in range(mid-1, l-1, -1):
			leftSum += nums[i]
			leftMax = max(leftMax, leftSum)
		
		# from mid to rightmost
		rightSum = nums[mid+1]
		rightMax = rightSum
		for i in range(mid+2, r+1):
			rightSum += nums[i]
			rightMax = max(rightMax, rightSum)
		
		return leftMax + rightMax

6.算法 - 回溯法

类似枚举,一层一层向下递归,尝试搜索答案

找到答案
尝试别的可能
返回答案

找不到答案
返回上一层递归,尝试别的路径

  1. 括号生成
class Solution(object):
	def generateParenthesis(self, n: int) -> List[str]:
		result = []
		self.backtracking(n, result, 0, 0, "")
		return result

	def backtracking(self, n, result, left, right, s):
		if right > left:
			return
		
		if (left == n and right == n):
			result.append(s)
			return
		
		if left < n:
			self.backtracking(n, result, left+1, right, s+"(")

		if right < n:
			self.backtracking(n, result, left, right+1, s+")")
  1. 子集

暴力法:

class Solution(object):
	# Time Complexity: O(N*2^N)
	# Space Complexity: O(N*2^N)
	def subsets(self, nums: List[int]) -> List[List[int]]:
		result = [[]]
		
		for num in nums:
			# result = result + [cur+[num] for cur in result]
			temp = []
			for cur in result:
				temp.append(cur+[num])
			for t in temp:
				result.append(t)
			
		return result

回溯法:

class Solution(object):
	# Time Complexity: O(N*2^N)
	# Space Complexity: O(N*2^N)
	def subsets(self, nums: List[int]) -> List[list[int]]:
		result = [[]]
		for i in range(1, len(nums)+1):
			self.backtracking(nums, result, i, 0, [])
		return result

	def backtracking(self, nums, result, length, index, subset):
		if len(subset) == lenth:
			result.append(subset[:])
			return
		
		for i in range(index, len(nums)):
			subset.append(nums[i])
			self.backtracking(nums, result, length, i+1, subset)
			subset.pop()

7.算法 - 深度优先搜索算法DFS

从root节点开始,尽可能深的搜索每一个分支(把一个分支的结果搜索完,再去看下一个分支)

  • 二叉树搜索
  • 图搜索

回溯算法 = DFS + 剪枝

  1. 子集
class Solution(object):
	# Time Complexity: O(N*2^N)
	# Space Complexity: O(N*2^N)
	def subsets(self, nums: List[int]) -> List[List[]]:
		result = []
		self.dfs(nums, result, 0, [])
		return result

	def dfs(self, nums, result, index, subset):
		result.append(subset[:])
		if index == len(nums);
			return
		for i in range(index, len(nums)):
			subset.append(nums[i])
			self.dfs(nums, result, i+1, subset)
			subset.pop()
  1. 岛屿数量
# R is the row of grid
# C is the column of grid
class Solution(object):
	# Time Complexity: O(RC)
	# Space Complexity: O(RC)
	def numIslands(self, grid: List[List[str]]) -> int:
		if grid is None or len(grid) == 0:
			return 0
		result = 0
		row = len(grid)
		col = len(grid[0])
		for i in range(0, row):
			for j in range(0, col):
				if grid[i][j] == '1':
					result = result + 1
					self.dfs(grid, i, j, row, col)
		return result
	
	def dfs(self, grid, x, y, row, col):
		if x < 0 or y < 0 or x >= row or y >= col or grid[i][j] == '0':
			return
		grid[x][y] = '0'
		self.dfs(grid, x-1, y, row, col)
		self.dfs(grid, x+1, y, row, col)
		self.dfs(grid, x, y-1, row, col)
		self.dfs(grid, x, y+1, row, col)
	

8.算法 - 广度优先搜索算法BFS

层层递进,一层一层遍历

  • 二叉树搜索
  • 图搜索
  1. 二叉搜索树的范围和
# Definition for a binary tree node.
# class TreeNode:
#	def __init__(self, val=0, left=None, right=None):
#		 self.val = val
#		 self.left = left
#		 self.right = right

class Solution(object):
	# Time Complexity: O(N)
	# Space Complexity: O(N)
	def rangeSumBST(self, root: TreeNode, low: int, high: int) -> int:
		result = 0
		queue = []
		queue.append(root)
		while len(queue) > 0:
			size = len(queue)
			while size > 0:
				cur = queue.pop()
				if cur.val >= low and cur.val <= high:
					result = result + cur.val
				if cur.left is not None:
					queue.append(cur.left)
				if cur.right is not None:
					queue.append(cur.right)
				size = size - 1
		return result
  1. 二叉树的层序遍历
from collections import deque

class Solution(object):
	# Time Complexity: O(N)
	# Space Complexity: O(N)
	def levelOrder(self, root: TreeNode) -> List[List[]]:
		result = []
		if roor is None:	
			return result
		
		q = deque([])
		q.append(root)
		while len(q) > 0:
			size = len(q)
			ls = []
			while size > 0:
				cur = q.popleft
				ls.append(cur.val)
				if cur.left is not None:
					q.append(cur.left)
				if cur.right is not None:
					q.append(cur.right)
				size = size - 1
			result.append(ls[:])
		return result
  1. 二叉树的层序遍历2
class Solution(object):
	# Time Complexity: O(N)
	# Space Complexity: O(N)
	def levelOrderBottom(self, root: TreeNode) -> List[List[int]]:
		result = []
		if root is None:
			return result
		
		q = deque([])
		q.append(root)
		temp = deque([])
		while len(q) > 0:
			size = len(q)
			ls = []
			while size > 0:
				cur = q.popleft()
				ls.append(cur.val)
				if cur.left is not None:
					q.append(cur.left)
				if cur.right is not None:
					q.append(cur.right)
				size = size - 1
			temp.appendleft(ls[:])
		result = list(temp)
		retutn result
  1. 岛屿数量
# R is the row of grid
# C is the column of grid
class Solution(object):
	# Time Complexity: O(RC)
	# Space Complexity: O(RC)
	def numIslands(self, grid: List[List[str]] -> int:
		if grid is None or len(grid) == 0:
			return 0
		result = 0
		row = len(grid)
		col len(grid[0])
		queue = []
		for i in range(0, row):
			for j in range(0, col):
				if grid[i][j] == '1':
					result = result + 1
					queue.append([i,j])
					grid[i][j] = '0'
					while len(queue) > 0:
						cur = queue.pop()
						x = cur[0]
						y = cur[1]
						if x-1 >= 0 and grid[x-1][y] == '1':
							queue.append([x-1, y])
							grid[x-1][y] = '0'
						if y-1 >= 0 and grid[x][y-1] == '1':
							queue.append([x][y-1])
							grid[x][y-1] = '0'
						if x+1 < row and grid[x+1][y] == '1':
							queue.append([x+1][y])
							grid[x+1][y] = '0'
						if y+1 < col and grid[x][y+1] == '1':
							queue.append([x][y+1])
							grid[x][y+1] = '0'
		return result
							

9.算法 - 并查集算法

Union:
合并两个元素为同一个根节点
Find:
找到某个元素的根节点

Union(x, y)
root Find(x)

  1. 岛屿数量
class Solution(object):
	# Time Complexity: O(RC)
	# Space Complexity: O(RC)
	def numIslands(self, grid: List[List[str]]) -> int:
		if grid is None or len(grid) == 0:
			return 0
		row = len(grid)
		col = lenj(grid[0])
		waters = 0
		uf = UnionFind(grid)
		for i in range(0, row):
			for j in range(0, col):
				if grid[i][j] == '0'
					waters += 1
				else:
					directions = [(0,1), (0,-1), (-1,0), (1,0)]
					for x, y in directions:
						x = x + i
						y = y + j
						if x>=0 and y>=0 and x<row and y<col and grid[x][y] == '1':
							uf.union(x*col+y, i*col+j)
		return uf.getCount() - waters

class UnionFind:
	def __init__(self, grid):
		row = len(grid)
		col = len(grid[0])
		self.root = [-1]*(row*col)
		self.count = row*col
		for i in range(0, row*col):
			self.root[i] = i
	def find(self, x):
		if x == self.root[x]:
			return self.root[x]
		else:
			self.root[x] = self.find(self.root[x])
			return self.root[x]
	def union(self, x, y):
		rootX = self.find(x)
		rootY = self.find(y)
		if rootX != rootY:
			self.root[rootX] = rootY
			self.count -= 1
	def getCount(self):
		return self.count
  1. 朋友圈

并查集优化

Quick Find

self.root[x] = self.find(self.root[x])
return self.root[x]

Quick Union - 权重
防止树太高
比较两个树的高
把矮的树连接到高的树上
使树的高度最低

if rootx != rooty:
	if self.rank[rootx] > self.rank[rooty]:
		root[rooty] = rootx
	elif self.rank[rootx] < self.rank[rooty]:
		root[rootx] = rooty
	else:
		root[rooty] = rootx
		self.rank[rootx] += 1

10.算法 - 贪心算法

每一步做出的都是当前看起来最好的选择
只是局部最优解
而不是整体的最优选择

  1. 零钱兑换

  2. 玩筹码

55.跳跃游戏


11.算法 - 记忆化搜索

减少重复计算

  1. 斐波那契数

  2. 零钱兑换


12.算法 - 动态规划

动态规划三要素

  • 初始状态
  • 方程式
  • 终止状态
  1. 计数:有多少种方法
    机器人从左上角到右下角有多少种路径

  2. 求最值:
    机器人从左到右路径的最大数字和

  3. 求存在性:是否存在某个可能
    是否存在机器人从左到右的路径

  4. 斐波那契数

  5. 不同路径

  6. 买卖股票的最佳时机

  7. 爬楼梯

  8. 完全平方数

  9. 最大正方形


学习视频来源B站—爱学习的饲养员—手把手带你刷Leetcode力扣

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值