自创算法——倍增查找

倍增查找

写在前面的声明

这个算法是本人在补CSP-S2024 t2时偶然想到的,目前网上没有看到类似的东西,所以写下这篇文章。

如果这个东西已经被人提出来了,可以把网址放在评论区。

发明原因和具体思路

考虑现在给你一个长度为 $ n $ 的单调不降序列 $ a $ ,求序列中不大于 $ x $ 的数字个数。

正常来做,直接一个二分秒了对不对。

但是如果当题目复杂一点,大多数人将分不清以下这几种二分选择哪种:

int l = 0,r = n;
while(l < r){//l <= r;  l < r - 1;  l <= r + 1;
    int mid = (l + r) >> 1;
    if(check(mid)) l = mid;//l = mid + 1;
    else r = mid;//r = mid - 1;
}
cout << l;//cout << r;

(图一中注释掉的代码表示其他可能的写法)

int l = 0,r = n;
int ans = 0;
while(l <= r){
    int mid = (l + r) >> 1;
    if(check(mid)) l = mid + 1,ans = mid;
    else r = mid - 1;
}
cout << ans;

这无疑会增加思考时间和调试时间。

于是,我们的倍增查找就横空出世了。

考虑最终的答案,它在二进制下每一位要么1要么0。

类似倍增的思路,我们从大到小枚举每一位,如果答案变量的这一位为1后,当前的答案位置满足要求,就使这一位为1。否则为0。

最终复杂度为 $ O(n*log_{2}n) $ 。

优点与缺点

优点:代码容易编写,调试简单,不容易出错。并且二分能干的它都能干。

缺点:时间复杂度的常数略劣于二分。因为二分的 $ O(n*log_{2}n) $ 跑不满(常数可能 $ < 1 $),但这个必然跑满。

总结与评价

实用性其实不高,毕竟实力稍微高一点(达到提高级),二分就算不能一次正确,也不会花太长时间调试。

不过这也是本人OI路上的一次探索,谨此留作怀念。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值