classSolution(object): defthreeSum(self, nums): """ :type nums: List[int] :rtype: List[List[int]] """ nums.sort() ans = [] n = len(nums) for i inrange(n-2): x = nums[i] if x + nums[i+1] + nums[i+2] > 0: break if nums[n-1] + nums[n-2] + nums[n-3] < 0: break if x + nums[n-1] + nums[n-2] < 0: continue if i > 0and x == nums[i-1]: continue j = i+1 k = n-1 while j < k: s = nums[i] + nums[j] + nums[k] if s > 0: k -=1 elif s < 0: j +=1 else: ans.append([nums[i],nums[j],nums[k]]) j = j+1 while j < k and nums[j] == nums[j-1]: j = j+1 k = k-1 while j < k and nums[k] == nums[k+1]: k = k-1 return ans
盛最多水的容器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
classSolution: defmaxArea(self, height: List[int]) -> int: ''' 1. ''' left = 0 right = len(height) - 1 ans = 0 while left < right: s = (right - left) * (min(height[left],height[right])) ans = max(ans,s) if height[left] < height[right]: left += 1 else: right -= 1 return ans
接雨水
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
classSolution: deftrap(self, height: List[int]) -> int: n = len(height) pre_max = [0] * n aft_max = [0] * n pre_max[0] = height[0] aft_max[-1] = height[-1] ans = 0 for i inrange(1,len(height)): max_num = max(pre_max[i-1],height[i]) pre_max[i] = max_num for j inrange(len(height)-2,-1,-1): max_num = max(aft_max[j+1],height[j]) aft_max[j] = max_num for k,pre,aft inzip(height,pre_max,aft_max): min_num = min(pre,aft) ans += (min_num - k) return ans
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
classSolution: deftrap(self, height: List[int]) -> int: n = len(height) left = 0 right = n - 1 pre_max = 0 aft_max = 0 ans = 0 while left <= right: pre_max = max(pre_max,height[left]) aft_max = max(aft_max,height[right]) if pre_max < aft_max: ans += pre_max - height[left] left += 1 else: ans += aft_max - height[right] right -= 1 return ans
滑动窗口
长度最小的子数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14
classSolution: defminSubArrayLen(self, target: int, nums: List[int]) -> int: n = len(nums) ans = n + 1 s = 0 left = 0 for right,x inenumerate(nums): s += x while s >= target: ans = min(ans,right - left + 1) s -= nums[left] left += 1 return ans if ans <= n else0
无重复字符的最长子串
1 2 3 4 5 6 7 8 9 10 11 12 13
classSolution: deflengthOfLongestSubstring(self, s: str) -> int: ans = 0 cut = Counter() left = 0 for right,x inenumerate(s): cut[x] += 1 while cut[x] > 1: cut[s[left]] -= 1 left += 1 ans = max(ans,right - left + 1) return ans
乘积小于k的子数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
classSolution: defnumSubarrayProductLessThanK(self, nums: List[int], k: int) -> int: if k <= 1: return0 ans = 0 s = 1 left = 0 for right,x inenumerate(nums): s *= x while s >= k: s //= nums[left] left += 1 ans += right - left + 1 return ans
# 写法一:求前缀和 from itertools import accumulate defget_sum(a): sum = list(accumulate(a)) returnsum # 写法二:求前缀和 defget_presum(a): n = len(a) sum = [0] * n sum[0] = a[0] for i inrange(1,n): sum[i] = sum[i-1] +a[i] returnsum
# 快速求区间和 defget_sum(sum,l,r): if l == 0: returnsum[r] else: returnsum[r] - sum[l-1]
a = [1,2,3,4,5] sum = get_presum(a) print(sum) #[1, 3, 6, 10, 15] he = get_sum(sum,3,4) print(he) #9
deftong_sort(a,bucketcount): """ :param a: 排序列表 :param bucketcount: 桶的数量 :return: """ minvalue,maxvalue = min(a),max(a) # 每个桶的大小,元素范围 bucketsize = (maxvalue - minvalue + 1) // bucketcount res = [[] for i inrange(bucketcount+1)] for x in a: idx = (x - minvalue) // bucketsize res[idx].append(x) ans = [] # 对每个桶中的元素排序 for x in res: x.sort() ans.extend(x) return ans
a = [1,6,3,5,8,2,1] res = tong_sort(a,min(1000,len(a))) print(res)
贪心
例题:
石子合并问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
import sys import heapq
input = lambda: sys.stdin.readline().strip() n = int(input()) a = list(map(int,input().split())) # 建一个堆 heapq.heapify(a) ans = 0 whilelen(a) != 1: x = heapq.heappop(a) y = heapq.heappop(a) heapq.heappush(a,x+y) ans += (x+y) print(ans)
# 请在此输入您的代码 input = lambda: sys.stdin.readline().strip() w = int(input()) n = int(input()) a = [] for i inrange(n): p = int(input()) a.append(p)
a.sort() l = 0 r = n-1 ans = 0 whileTrue: if l == r: ans += 1 break if l > r: break if a[l] + a[r] <= w: l += 1 r -= 1 ans += 1 else: r -= 1 ans += 1 print(ans)
import sys n = 7 ans = 0 temp = [[0,0] for i inrange(7)]
defdfs(deepth): if deepth == n: sum1 = 0 sum2 = 0 for x inrange(n): sum1 += temp[x][0] sum2 += temp[x][1] if sum1 == 9and sum2 == 16: global ans ans += 1 return for i inrange(0,6): for j inrange(0,6): if2<= i+j<=5: temp[deepth][0] = i temp[deepth][1] = j dfs(deepth+1)
import os import sys sys.setrecursionlimit(100000) # 请在此输入您的代码 input = lambda: sys.stdin.readline().strip() n = int(input()) MAP = [] vits = [] ans = 0 for i inrange(n): MAP.append(list(input())) vits.append([0] * n)
defdfs(x,y): # 标记当前点 vits[x][y] = 1 # 判断当前点是否为高地 if MAP[x][y-1] == "#"and MAP[x][y+1] == "#"and MAP[x-1][y] == "#"and MAP[x+1][y] == "#": global flag flag = True # 把四周未遍历的土地继续遍历 for dir_x,dir_y in ([0,-1],[0,1],[-1,0],[1,0]): xx = x + dir_x yy = y + dir_y if MAP[xx][yy] == "#"and vits[xx][yy] == 0: dfs(xx,yy)
for x inrange(n): for y inrange(n): if MAP[x][y] == "#"and vits[x][y] == 0: flag = False dfs(x,y) if flag == False: ans += 1 print(ans)
import os import sys from functools import lru_cache
# 请在此输入您的代码 input = lambda: sys.stdin.readline().strip() n,m,k = map(int,input().split()) A,B,C,D = map(int,input().split()) A -= 1 B -= 1 C -= 1 D -= 1 MAP = [] for i inrange(n): MAP.append(list(map(int,input().split()))) @lru_cache(maxsize=None) defdfs(x,y,z): if x == C and y == D: returnTrue for dir_x,dir_y in [(0,1),(1,0),(-1,0),(0,-1)]: xx,yy = dir_x + x,dir_y + y if0 <= xx < n and0 <= yy < m: if MAP[xx][yy] < MAP[x][y]: if dfs(xx,yy,z): returnTrue elif z == Falseand MAP[x][y] + k > MAP[xx][yy]: if dfs(xx,yy,True): returnTrue else: continue
import os import sys from functools import lru_cache
# 请在此输入您的代码 input = lambda: sys.stdin.readline().strip() n,m,k = map(int,input().split()) MAP = [] for i inrange(n): MAP.append(list(map(int,input().split()))) @lru_cache(maxsize=None) defdfs(x,y,z,w): # x,y代表当前位置 # z代表当前宝贝的件数 # w代表当前得到的宝贝中价值最大的 if x == n - 1and y == m - 1: # 当前不需要选择 if z == k: return1 # 当前需要选择 if z == k - 1and MAP[x][y] > w: return1 return0 ans = 0 for dir_x,dir_y in [(0,1),(1,0)]: xx,yy = x + dir_x,y + dir_y if xx < n and yy < m: # 不拿宝贝 ans += dfs(xx,yy,z,w) # 拿宝贝 if MAP[x][y] > w: ans += dfs(xx,yy,z+1,MAP[x][y]) else: continue return ans % 1000000007 print(dfs(0,0,0,-1))
B = 26 mod = 1000000007 defHash(s): res = 0 for c in s: res = res * B + ord(c) - ord('A') res %= mod return res
t = input() s = input() m,n = len(t),len(s), numT = Hash(t) hash = [0] for c in s: hash.append((hash[-1] * B + ord(c) -ord('A')) % mod) ans = 0 p = (B ** m) % mod # 枚举所有区间[l,l+m-1] for l inrange(1,n+1): r = l + m - 1 if r > n: break if (hash[r] - hash[l-1] * p % mod +mod)%mod == numT: ans += 1 print(ans)
n,m = map(int,input().split()) p = list(range(n+1)) for _ inrange(m): op,x,y = map(int,input().split()) if op == 1: Merge(x,y) else: if Query(x,y): print("YES") else: print("NO")
MOD = 1000000007 n, k = map(int, input().split()) dp = [0] * (n + 1) dp[0] = 1 for i inrange(1,n+1): if i - k - 1 >= 0: dp[i] = (dp[i-1] + dp[i-k-1]) % MOD else: dp[i] = (dp[i-1] + 1) % MOD print(dp[n])
二维dp
树形dp
状压dp
数位dp
图论
欧拉回路
最小生成树
单源最短路
杂项
判断是否为质数
1 2 3 4 5 6 7 8 9 10 11 12 13
defis_zhishu(n): if n <= 1: returnFalse if n <= 3: returnTrue if n % 2 == 0or n % 3 == 0: returnFalse i = 5 while i * i <= n: if n % i == 0or n % (i + 2) == 0: returnFalse i += 6 returnTrue
埃拉托斯特尼筛法
用于找出小于或等于给定整数 n 的所有素数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
deffunc(n): isprime = [True] * (n + 1) # 0 和 1 不是素数 isprime[0] = isprime[1] = False result = [] for i inrange(2, n + 1): # 如果当前数字是素数 if isprime[i]: result.append(i) # 对于素数 i,将其所有大于 i 的倍数标记为非素数。 # 这一步的核心思想是:如果一个数是某个素数的倍数,那么它一定不是素数。 for j inrange(i * 2, n, i): isprime[j] = False return result
for i inrange(2, n + 1): if isprime[i]: # 如果 i 是素数 # 将 i 的倍数标记为非素数(即合数) for j inrange(i * 2, n + 1, i): if isprime[j]: # 如果 j 尚未被标记为合数 isprime[j] = False composites.append(j) # 收集合数