目录
前缀和
前缀和即为sum[i] = a[0] + a[1] + ... + a[i]
另一种方法是迭代器求
二维前缀和
差分
有一性质:差分数组的前缀和等于元素组
二维差分数组
离散化
离散化:不关注数字大小本身多少,只关心大小关系,用排名替代原数据。
本质上是一种哈希映射,将离散的数字、浮点数,转换成1~n
from bisect import * def Discrete(a): #排序去重(集合可以去重) b=list(set(a)) b.sort() ans=[] for i in range(len(a)): #二分查找,找a[i]在去重后的b中的索引 ans.append(bisect_left(b,a[i])) return ans a=list(map(int,input().split())) print(Discrete(a))
贪心
但并不是所有局部最优能得到全局最优,例子如下:
之所以前一个例子可以用贪心,是因为最大面值的5元,大于其他小面值1元和2元之和(1+2<5);而后面一个例子不是。
例子:
思路:每次考虑人数最小的两个部落合并。
n=int(input()) a=list(map(int,input().split())) #堆,每次获取最小元素、添加元素 heapq.heapify(a) #每次把最小的两个数相加,直到堆的长度为1停止 ans=0 while len(a)>=2: x=heapq.heappop(a) y=heapq.heappop(a) heapq.heappush(a,x+y) ans+=x+y print(ans)
双指针
反向扫描:
例题:判断回文字符
s=input() l,r=0,len(s)-1 ok='Y' while l<=r: if s[l]==s[r]: l+=1 r-=1 else: ok='N' break print(ok) s=input() # 直接翻转字符串 if s==s[::-1]: print('Y') else: print('N')
同向扫描:
例题:
n,S=map(int,input().split()) a=list(map(int,input().split())) #找满足区间和>=S的最短区间长度 min_len=n+1 left,right=0,0 tot=0 while left<n: #right向右走 while right<n and tot<S: tot+=a[right] right+=1 if tot>=S: min_len=min(min_len,right-left) #left向右走 tot-=a[left] left-=1 print(min_len)
二分法
位运算
左移是指把二进制向左移动,空出来的位置补0
位运算技巧: