探索C++双指针算法:原理、应用与实战代码详解

引言

🌟双指针算法,一种强大的编程工具,以其高效性和简洁性深受算法爱好者和专业开发者的喜爱。这一经典策略在处理线性数据结构时能极大优化复杂度,今天我们将深入探讨其内在原理,并通过实际案例演示如何在C++中巧妙运用。
学习双指针算法在解题的时候有妙用,通常可以降低算法的时间复杂度,希望给大家一点参考,记录学习的同时,也希望大家批评指正,谢谢大家!!

1️⃣ 双指针算法原理

💡双指针并非字面意义上的“指针”,而是通常用来描述两个变量作为索引在数组或链表中同步或异步移动的过程。这种技术的核心在于利用两个指针分别从不同位置开始遍历,以减少不必要的重复计算,快速定位问题答案。

2️⃣ 使用场景

🎯常见的双指针算法应用场景包括但不限于:

  • 查找数组中和为目标值的元素对/三元组(例如 “和为S的两个数” 或 “三数之和” 问题)
  • 寻找旋转数组中的最小或最大元素
  • 解决滑动窗口相关问题,如最大子数组和、最接近目标值的子数组等
  • 判断回文串、寻找有效括号字符串等字符串处理问题
  • 快慢指针查找环形链表入口节点及判断链表是否有环

3️⃣ 示例代码与解析

📚下面是一个实例——查找数组中两个数相加等于给定值的C++代码片段:

#include <vector>
using namespace std;

bool twoSum(vector<int>& nums, int target) {
    int left = 0, right = nums.size() - 1;
    
    while (left < right) {
        int currentSum = nums[left] + nums[right];
        
        if (currentSum == target) {
            return true;
        } else if (currentSum < target) {
            ++left;
        } else {
            --right;
        }
    }
    return false;
}

上述代码展示了双指针如何从数组两端向中间靠拢,不断调整指针位置直到找到满足条件的元素对。

4️⃣ 注意事项

⚠️在使用双指针时需要注意以下几点:

  • 确保数据结构适合双指针方法,比如已排序数组或特定规律的数组。
  • 初始化指针时要考虑边界条件,避免数组越界。
  • 根据具体问题选择合适的移动策略,如同时向内移动、向中心收缩或一快一慢等。
  • 对于动态变化的数据结构,如链表,可能需要额外考虑指针指向的有效性。

!!!能使用双指针算法,当且仅当一个下标关于另一个下标单调!

补充案例以及手推案例

y总 牛的学术圈1
由于对计算机科学的热爱,以及有朝一日成为 「Bessie 博士」的诱惑,奶牛 Bessie 开始攻读计算机科学博士学位。经过一段时间的学术研究,她已经发表了 N 篇论文,并且她的第 i 篇论文得到了来自其他研究文献的 ci 次引用。Bessie 听说学术成就可以用 h指数来衡量。h指数等于使得研究员有至少 h篇引用次数不少于 h的论文的最大整数 h。

例如,如果一名研究员有 4篇论文,引用次数分别为 (1,100,2,3),则 h 指数为 2,然而若引用次数(1,100,3,3),则 h指数将会是 3。

为了提升她的 h指数,Bessie 计划写一篇综述,并引用一些她曾经写过的论文。由于页数限制,她至多可以在这篇综述中引用 L篇论文,并且她只能引用每篇她的论文至多一次。请帮助 Bessie 求出在写完这篇综述后她可以达到的最大 h指数。

注意 Bessie 的导师可能会告知她纯粹为了提升 h指数而写综述存在违反学术道德的嫌疑;我们不建议其他学者模仿 Bessie 的行为。

输入格式:
输入的第一行包含 N和 L。
第二行包含 N个空格分隔的整数 c1,…,cN。

输出格式:
输出写完综述后 Bessie 可以达到的最大 h指数。

数据范围
1≤N≤105,
0≤ci≤105,
0≤L≤105

输入样例1:

4 0
1 100 2 3

输出样例1:

2

样例解释
Bessie 不能引用任何她曾经写过的论文。上文中提到,(1,100,2,3)的 h指数为 2。

题解参考:题解

#include<iostream>
#include<algorithm>
using namespace std;
int q[100010];
int n,k;//有N(n)篇论文,在综述中引用L(k)篇
int main()
{
    int an=0;
    cin >> n >> k;
    for(int i=1;i<=n;i++)cin >> q[i];
    sort(q+1,q+1+n,greater<int>());
    for(int i=1,j=n;i<=n;i++)
    {//在此i为指数
        while(j&&q[j]<i)j--;//从右往左第一个大于i的q[];
        if(q[i]>=i-1&&i-j<=k)//最小的q[]大于i-1,最大的位置数i减去最小的位置j:i-j小于可引用次数 即成立。维护i-1这个区间并于L做比较
        an=i;//更新高引指数h(an)。
    }
    cout << an;
}

手推过程(小白狂喜):
冰指绕温手推

结语

💪理解并熟练掌握双指针算法不仅能提升编码效率,更能锻炼逻辑思维能力。无论是在面试还是项目开发中,适时运用双指针对解决问题都能起到事半功倍的效果。现在就开始在实践中运用双指针算法,感受它带来的编程魅力吧!


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值