【C++】使用双指针算法习题


🎆个人主页:夜晚中的人海

今日语录:用乐观的心态迎接困难,因为能打败你的,只有你自己。

文章目录

一、移动零

题目链接:移动零

题目描述:

解题思路:

1.我们可以使用两个指针cur和dest,一个指针(cur)负责遍历整个数组,另一个指针(dest)用来记录非零序列

2.在遍历过程中会出现两种情况,一个是当遇到的元素为0时,cur直接++;相反当遇到的元素为非0时,让dest指针先自增一(由于不知道最后⼀个非零元素在什么位置,因此初始化为-1 ),与cur指针指向的元素进行交换,不断重复上述过程就可以解决这一类问题

代码实现:

cpp 复制代码
class Solution 
{
public:
 void moveZeroes(vector<int>& nums) 
 {
 for(int cur = 0, dest = -1; cur < nums.size(); cur++)
 		if(nums[cur]) 
 				swap(nums[++dest], nums[cur]);
 }
};

二、复写零

题目链接:复写零

题目描述:

解决思路:

1.我们使用两个指针cur和dest,当cur小于数组个数时,不断重复下述过程: 判断cur指向的数据元素,如果它为0,那么dest指针移动两位,否则移动一位,每判断完一次cur指针都需要++

2.判断dest指针是否越界到数组大小为n的位置上,如果越界,则直接将数组中最后一个位置赋值给0,然后对两个指针进行回退,cur指针退一步,dest指针退两步

3.然后对数组进行复写,判断cur当前位置是否为0,如果不为0,则将cur位置的值赋值给dest,然后两个指针分别--,否则将dest位置修改为0,重复两次该操作,然后让cur--

代码实现:

cpp 复制代码
class Solution {
public:
    void duplicateZeros(vector<int>& arr) {
        int cur = 0,dest = -1;
        int n = arr.size();
        while(cur < n)
        {
            if(arr[cur])
                dest++;
            else
                dest += 2;
            if(dest >= n - 1)
            {
                break;
            }
            cur++;
        }
        //处理边界情况
        if(dest == n)
        {
            arr[n - 1] = 0;
            cur--;
            dest -= 2;
        }
        while(cur >= 0)
        {
            if(arr[cur])
            {
                arr[dest--] = arr[cur--];
            }
            else
            {
                arr[dest--] = 0;
                arr[dest--] = 0;
                cur--;
            }
        }
    }
};

三、快乐数

题目链接:快乐数

题目描述:

解题思路:
我们可以使用快慢指针的方法 ,由于快慢指针的特性(注:就是在一个环中,快指针总会追上慢指针,也就是它们会相遇在一个位置上),当相遇位置的值为1时,则这个数为快乐数,否则不是

代码实现:

cpp 复制代码
class Solution {
public:
    int bitsum(int num)
    {
        int sum = 0;
        int i;
        while(num)
        {
            i = num % 10;
            sum += i * i;
            num /= 10;
        }
        return sum;
    }

    bool isHappy(int n) {
        int slow = n,fast = bitsum(n);
        while(slow != fast)
        {
            slow = bitsum(slow);
            fast = bitsum(bitsum(fast));
        }
        return slow == 1;
    }
};

四、有效三角形的个数

题目链接:有效三角形的个数

题目描述:

解题思路:

一、我们可以使用暴力求解的方法,使用三层for循环,枚举出所有的三元组,判断是否构成三角形。但这个方法的时间复杂度太高了,效率低,因此采用另一种方法

二、我们可以对数组先进行排序,然后固定一个最长边nunsi,使用两个指针left和right(left < right),采用对撞指针的方法,一个指向开头位置,另一个指向i - 1的位置上,如果numsleft + numsright > numsi,那么满足条件的三角形个数就为right - left,然后让right--再进行判断,否则让left++,不断重复上述过程

代码实现:

cpp 复制代码
class Solution {
public:
    int triangleNumber(vector<int>& nums) {
        sort(nums.begin(),nums.end());
        int n = nums.size();
        int ret = 0;
        for(int i = n - 1;i >= 2;i--)
        {
            int left = 0,right = i - 1;
            while(left < right)
            {
                if(nums[left] + nums[right] > nums[i])
                {
                    ret += right - left;
                    right--;
                }
                else
                {
                    left++;
                }
            }
        }
        return ret;
    }
};

五、和为s的两个数字

题目链接:和为s的两个数字

题目描述:

解题思路:

一、暴力求解:使用两层for循环,列出所有两个数字的组合,判断是否等于目标值(结果会超时)

二、使用对撞指针,一个指针left指向开头,另一个指针right指向数组最后一个的位置(left < right),判断priceleft + priceright是否等于target,如果大于则让right--,否则让left++,不断重复此过程

代码实现:

cpp 复制代码
class Solution {
public:
    vector<int> twoSum(vector<int>& price, int target) {
        int n = price.size();
        int left = 0,right = n - 1;
        while(left < right)
        {
            if(price[left] + price[right] > target)
            {
                right--;
            }
            else if(price[left] + price[right] < target)
            {
                left++;
            }
            else
            {
                return {price[left],price[right]};
            }
        }
        //照顾编译器
        return {1,1};
    }
};
相关推荐
GKxx2 小时前
在 HarmonyOS 上从源码构建 GCC 16(gcc/g++ + libstdc++ + libsanitizer):完整记录
c++·华为·harmonyos·鸿蒙·gcc
晴天的雨.9922 小时前
类和对象下(内部类,匿名对象,对象拷贝时的编译器优化)
开发语言·c++·算法
其实防守也摸鱼2 小时前
智能体推荐:精选 AI Agent 工具与实战指南
运维·开发语言·人工智能·学习·web安全·自动化
always_TT2 小时前
【Python 字符串格式化:format() 方法】
android·开发语言·python
小义_2 小时前
JDK 深度解析
java·linux·开发语言·python·面试
旖旎夜光2 小时前
LeetCode 238:除自身以外数组的乘积(前缀和) —— 题解
数据结构·c++·算法·leetcode·前缀和
智购科技自动售货机工厂2 小时前
2026自动售货机异常重启根因分析:从日志挖掘到内存取证的技术实践~YH
开发语言·数据库·单片机·嵌入式硬件·人机交互
一条大祥脚3 小时前
26杭电暑期第八场(后半)快读|快写|tarjan|路径DP|mex转化|扫描线|前缀和|二分图
数据结构·算法·tarjan·杭电多校·强联通分量·动态规划dp
奈斯先生Vector3 小时前
从“能调用”到“可运营”:AI Agent 进入多模型时代后的架构升级
java·javascript·数据库·人工智能·算法·架构·aigc
Escalating_xu3 小时前
【C++类和对象(上)】从类的定义、封装与对象模型到内存对齐和 this 指针
开发语言·前端·c++