代码随想录 一星期总结 3.23-3.30
数组专题:
主要是二分 以及双指针让我影响深刻
二分:
二分的本质其实是一个区间 分成两段 一段满足一个性质,另一段满足另一个性质,而不是有序,单调等
然后我们的两个模板对应着求这两个指针的位置
模板1 (求绿色指针):
int left=0,right=n-1;
while(left<right)
{
int mid=left+right+1>>1; #这里要加1 不加1 会造成循环
if(check(mid))
{ #如果满足绿色性质
left=mid;
}
else right=mid-1; #说明你在粉色那个区域
}
#出来的时候 left =right 绿色的指针就求出来了
模板2 (求粉色指针)
int left=0,right=n-1;
while(left<right)
{
int mid=left+right>>1; #这里不用加1
if(check(mid))
{ #如果满足粉色性质
right=mid;
}
else left=mid+1; #说明你在绿色那个区域
}
#出来的时候 left =right 粉色的指针就求出来了
双指针:
双指针很多应用 而且双指针都有一个特性 就是暴力求解
就是你先想一个暴力求解思路 然后对其进行优化.
双指针 大概长这样:
for(int i=0,j=0;i<n;i++)
{
while(j<i &&check(j,i))
{
j++;
}
}
当然 这只是大概长这样 当面对不同的题目 肯定有不同的写法
其中check 就可以拆开 因为有些题目 可能单算这个区间的复杂度就是n
然后遍历这两个指针n 最后成了n^2
所以要优化成O(n) check 函数一般要保持O(1) 但是O(1) 的话可能就得维护一个区间了 而不是先定个头再定个尾 再求答案.
比如 最小覆盖字串 在没有学哈希之前 验证一个字符串是否覆盖另一个字符串的时候就是O(n) 如果不维护区间的信息 全部丢掉那就一直是O(N)
最后复杂度就变成了 O(N^2)
i与j的含义就是 区间头与区间尾
当然 学了hash 之后 check 就变成了 O(1)
哈希!!! yyds
链表:
很多地方用到了双指针不过不是上面的那个形式
这种双指针用来标记的成分更多 比如删除 倒数第k个数 找公共交点
这种会灵活一点 但一般都能想到
印象深刻的有一题 找环入口的
当时自己想的一个维护一个堆咯 nlogn 无奈之举
我现在突然发现有了hash 好像直接变成 O(n) 直接把地址当字符存就好了
反正字符hash 基本不会有重复的存在 (这个假设挺逆天的)
正规做法:
一个fast 指针 一个 slow 指针
f=2s 相遇时 f=s+nb 所以 s=nb 然后 又因为 入口等于 a+nb 所以让s加上a
a又代表着从开始到入口的结点 所以让f指针指会开头跟着s一直move 相遇的时候就是入口 我只能说 6
哈希:
刚开始看这个哈希 目前呢 文章上写的就是 三种数据结构
分别时 set map unordered_set unordered_map 以及 multiset multimap
unordered 用哈希表实现 其他两种都是 红黑树
红黑树具体是啥 不知道好吧
哈希表 讲了 开放寻址法 也就是 线性… 还讲了拉链法
const int h[N]; #N一般是大于使用个数的第一个 质数 会减少碰撞次数
int find(int x)
{
int k=(x%N+N)%N;
while(h[k]!=null && h[k]!=x)
{
#如果有元素且那个元素又不是x 那就继续找
k++;
}
return k;
#这里返回的k 即代表 x应该在的位置记住是 应该在而不是 在
#所以你后面拿这个h[k]位置判断一下 如果不在那就是没有
}
字符串哈希:
这个比较逆天
一个字符串我们该怎么哈希呢
比如 “daCSA/?saB@-c’”
有一个叫p进制的 故名意思 每一个字符都是p进制的一个数
因为这些字符都是ascii码 无非就是128个数
所以p进制 合理 假设ascii 中 d是 4
那 d就是p进制中 第四个数子
且这一串p进制转成10进制的话就是
4 x p**(s.size()-1)+1 x p**(s.size()-2)+…+ 3 x p**0
然后我们就能用十进制来代表这个字符串了 合理极了
那么 数字太大了 我们使用 unsigned long long 来限制它的范围为2^64
也就是 [0,2^64]之内
那如果冲突呢 我两个不一样字符串 本来好好的变成十进制数不一样
但是你一模 给我模成一样了 你怎么办呢
经验告诉我们 q=131 或1331 ,N取2^64 时 基本不会有冲突
也就是你几乎找不到两个不一样的字符串 模完相等的
我对这个假设的评价是 6
当然有一个 叫 哈希前缀和的 这个东西有点像前缀和
求字串的hash能做到O(1)
h[l,r]=h[r]-h[l-1]*p^(r-l+1)