首页 > 编程语言 >【C++算法】双指针

【C++算法】双指针

时间:2024-08-11 19:53:06浏览次数:12  
标签:right cur nums int C++ height 算法 指针 left

移动零

题目链接:移动零icon-default.png?t=N7T8https://leetcode.cn/problems/move-zeroes/description/

  • 算法原理

这类题是属于数组划分、数组分开题型

  • 代码步骤:
  1. 使用cur遍历数组
  2. 当cur所指的元素等于0时,cur向后面移动
  3. 当cur所指的元素不等于0时,dest向后面移动,cur所指元素与dest移动后所指的元素交换
  4. 当cur指向最后一个元素的下一个时,结束。
  • 代码展示
class Solution {
public:
    void moveZeroes(vector<int>& nums) 
    {
        int dest = -1;
        for(int cur = 0; cur < nums.size(); ++cur)
        {
            //如果cur所指的元素非0,交换
            if(nums[cur] != 0)
            {
                swap(nums[++dest], nums[cur]);
            }
        }
    }
};

复写零

题目链接:

复写零icon-default.png?t=N7T8https://leetcode.cn/problems/duplicate-zeros/description/

  • 算法原理

  • 代码步骤:

  • 代码展示
class Solution {
public:
    void duplicateZeros(vector<int>& arr) 
    {
        //寻找复写的最后一个元素
        int cur = 0;
        int dest = -1;
        int n = arr.size();
        //注意arr.sizr()是size_t无符号类型
        //int(-1)比size_t整数大
        while(cur < n)
        {
            if(arr[cur])
            {
                ++dest;
            }
            else
            {
                dest += 2;
            }
            //注意这个判断条件需要在里面实现
            //如果在整个循环结束判断,cur的值无法保证
            if(dest >= n-1) break;
            cur++;
        }
        //特殊情况处理
        if(dest == n)
        {
            arr[n - 1] = 0;
            --cur;
            dest -= 2;
        }
        //进行从右向左的复写操作
        for(; cur >= 0; --cur)
        {
            if(arr[cur])
            {
                arr[dest--] = arr[cur];
            }
            else
            {
                arr[dest--] = 0;
                arr[dest--] = 0;
            }
        }  
    }
};

快乐数

题目链接:

快乐数icon-default.png?t=N7T8https://leetcode.cn/problems/happy-number/submissions/552733314/

  • 算法原理

  • 代码步骤:

采用快慢双指针的思想:

  1. 定义快慢双指针
  2. 设置一个每个位置平方和的函数
  3. 慢指针每次向后移动一步
  4. 快指针每次向后移动俩步
  5. 判断快慢指针相遇的时候的值是否为1即可
  • 代码展示
class Solution {
public:
    //计算数每个位置上数字的平方和
    int SquareSum(int n)
    {
        int sum =0;
        while(n > 0)
        {
            int num = n % 10;
            sum += num * num;
            n /= 10;
        }
        return sum;
    }
    bool isHappy(int n) 
    {
        int slow = n;
        int fast = SquareSum(n);
        while(slow != fast)
        {
            fast = SquareSum(SquareSum(fast));
            slow = SquareSum(slow);
        }
        if(slow == 1)
        {
            return true;
        }
        else 
        {
            return false;
        }
    }
};

盛最多水的容器

题目链接:

盛最多水的容器icon-default.png?t=N7T8https://leetcode.cn/problems/container-with-most-water/

  • 算法原理

  • 代码步骤:
  1. 记录初始w最大时的初始容积
  2. left与right二者中较小者向里面移动,寻找比自己大的值
  3. 找到比自己大的值,记录面积,并与之前的面积比较大小
  4. 当left与right相遇的时候,结束
  • 代码展示
class Solution 
{
public:
    int maxArea(vector<int>& height) 
    {
        int left = 0;
        int right = height.size() - 1;
        //寻找边界的最小值
        int min = (height[left] < height[right]) 
        ? height[left] 
        : height[right];
        //起始容积
        int vmax = min * (right - left);
        while(left < right)
        {
            if(height[left] < height[right])
            {
                //记录此时的left
                int num = left;
                while(left < right)
                {
                    //比较看是否有比height[left]大的值
                    ++left;
                    if(height[num] < height[left])
                    {
                        break;
                    }
                }
            }
            else
            {
                //记录此时的left
                int num = right;
                while(left < right)
                {
                    //比较看是否有比height[left]大的值
                    --right;
                    if(height[num] < height[right])
                    {
                        break;
                    }
                }
            }
            min = (height[left] < height[right]) 
            ? height[left] 
            : height[right];
            int v = min * (right - left);
            vmax = (v > vmax) ? v : vmax; 
        }
        return vmax;
    }
};
class Solution {
public:
    int maxArea(vector<int>& height) 
    {
        int left = 0, right = height.size() - 1, vmax = 0;
        while(left < right)
        {
            int v = min(height[left], height[right]) * (right - left);
            vmax = max(vmax, v);
            if(height[left] < height[right]) ++left;
            else --right;
        }
        return vmax;
    }
};

有效三角形个数

题目链接:

有效三角形个数icon-default.png?t=N7T8https://leetcode.cn/problems/valid-triangle-number/

  • 算法原理

  • 代码步骤:
  1. 对数组进行排序
  2. 设置三个指针,一个指向最大值,另外俩个形成单调双指针
  3. 当left + right < max时,个数为right-left,right--
  4. 当left + right >= max时,个数为0,left++
  • 代码展示
class Solution {
public:
    int triangleNumber(vector<int>& nums) 
    {
        int n = nums.size();
        //排序升序
        sort(nums.begin(), nums.end());
        int sum = 0;
        //最大值向前移动
        while(n >= 2)//确保right不越界
        {
            int max = nums[n - 1];
            int left = 0, right = n - 2;
            //利用单调性使用双指针
            while(left < right)
            {
                if(nums[left] + nums[right] > max)
                {
                    sum += (right - left);
                    right--;
                }
                else
                {
                    left++;
                }
            }
            --n;
        }
        return sum;
    }
};

三数之和

题目链接:

三数之后icon-default.png?t=N7T8https://leetcode.cn/problems/3sum/

  • 算法原理

  • 代码步骤:
  1. 排序
  2. 固定一个数min(注意当min > 0的时候,也是可以直接结束的)
  3. 在该数的后面的区间之内,利用单调性使用双指针,快速找到俩个和等于-min的值
  4. 细节1:不漏数据
  5. 细节2:去重操作
  • 代码展示
class Solution 
{
public:
    vector<vector<int>> threeSum(vector<int>& nums) 
    {
        vector<vector<int>> vv;
        //排序
        sort(nums.begin(), nums.end());
        int n = nums.size();
        //固定一个数
        int min = 0;
        for(int min = 0; min < n - 2; ++min)
        {
            //优化
            if(nums[min] > 0) break;
            int left = min + 1, right = n - 1;
            while(left < right)
            {
                if(nums[left] + nums[right] < -nums[min])
                {
                    left++;
                }
                else if(nums[left] + nums[right] > -nums[min])
                {
                    right--;
                }
                else
                {
                    //添加数据
                    vv.push_back({nums[min], nums[left], nums[right]});
                    while(left < right && nums[left] == nums[left + 1])
                    {
                        left++;
                    }
                    while(left < right && nums[right] == nums[right - 1])
                    {
                        right--;
                    }
                    if(left < right)
                    {
                        left++;
                        right--;
                    }
                }
            }
            while(min < n - 2 && nums[min] == nums[min + 1])
            {
                min++;
            }
        }
        return vv;
    }
};

四数之和

题目链接:

四数之和icon-default.png?t=N7T8https://leetcode.cn/problems/4sum/description/

  • 算法原理

  • 代码步骤:

  • 代码展示
class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) 
    {
        vector<vector<int>> ret;
        //排序
        sort(nums.begin(), nums.end());
        int n = nums.size();
        //四数之和
        for(int minA = 0; minA < n;)
        {
            long targetA = target - nums[minA];
            //三数之和
            for(int minB = minA + 1; minB < n;)
            {
                long targetB = targetA - nums[minB];
                int left = minB + 1, right = n - 1;
                while(left < right)
                {
                    //利用单调性使用双指针
                    if(nums[left] + nums[right] < targetB)
                    {
                        left++;
                    }
                    else if(nums[left] + nums[right] > targetB)
                    {
                        right--;
                    }
                    else
                    {
                        ret.push_back({nums[minA], nums[minB], nums[left], nums[right]});
                        //left不重
                        while(left + 1 < right && nums[left] == nums[left + 1])
                        {
                            left++;
                        }
                        //right不重
                        while(left < right - 1 && nums[right] == nums[right - 1])
                        {
                            right--;
                        }
                        //不漏
                        if(left < right)
                        {
                            left++;
                            right--;
                        }
                    }
                }
                //minB不重
                while(minB + 1 < n && nums[minB] == nums[minB + 1])
                {
                    minB++;
                }
                ++minB;
            }
            //minA不重
            while(minA + 1 < n && nums[minA] == nums[minA + 1])
            {
                minA++;
            }
            ++minA;
        }
            return ret;
    }
};  

标签:right,cur,nums,int,C++,height,算法,指针,left
From: https://blog.csdn.net/dab112/article/details/140723680

相关文章

  • 第九天:K-Means算法
    K-Means算法简介K-Means算法是一种广泛使用的聚类算法,旨在将数据集分成K个预定义的簇。每个簇的中心是簇中所有点的均值,称为质心。K-Means算法的目标是最小化每个数据点到其所属簇的质心的距离的平方和。算法原理K-Means算法的工作原理可以分为以下几个步骤:初始化:随机......
  • C++虚函数表、地址详解(x86/x64)
    参考博文:c++虚函数表、地址详解-CSDN博客本文在上述博文的基础上,补充了x64下的验证代码。一.什么是虚函数表,它有什么特点?        虚函数大家都知道是基本用于实现多态的,当父类指针指向子类对象的时候,如何确定调用的函数是父类里的还是子类里面的,这就要用到虚函数表......
  • 病毒分享(C++)[1]
    今天我给大家分享的是勒索病毒C++版,代码如下,可以《免费》复制。#include<bits/stdc++.h>#include<iostream>#include<cstdlib>#include<cstdlib>#include<ctime>#include<Windows.h>#define_CRT_SECURE_NO_WARNINGS1#pragmacomment(lib,"winmm.li......
  • 【C++】using
    对C++中using关键字的几种用法的总结:1、using声明using声明(usingdeclaration)是将命名空间中单个名字注入到当前作用域的机制,使得在当前作用域下访问另一个作用域下的成员时无需使用限定符:://...{usingstd::mapmap<int,std::string>the_map;//ok}ma......
  • 算法题系列5
    题目描述模拟一套简化的序列化传输方式,请实现下面的数据编码与解码过程1.编码前数据格式为[位置,类型,值],多个数据的时候用逗号分隔,位置仅支持数字,不考虑重复等场景;类型仅支持:Integer/String/Compose(Compose的数据类型表示该存储的数据也需要编码)2.编码后数据参考图示,数据......
  • 【C++】typeid与RTTI
    1、简介注意:typeid是操作符,不是函数。这点与sizeof类似)运行时获知变量类型名称,可以使用typeid(变量).name()需要注意不是所有编译器都输出”int”、”float”等之类的名称,对于这类的编译器可以这样使用。intia=3;if(typeid(ia)==typeid(int)){cout<<"int"<<e......
  • 用电量预测 | 基于BiLSTM双向长短期记忆神经网络算法的用电量预测附matlab完整代码
    用电量预测|基于BiLSTM双向长短期记忆神经网络算法的用电量预测附matlab完整代码数据收集:收集历史用电量数据,包括时间戳和相应的用电量值。选择模型:选择合适的模型进行预测,可以根据数据特点和需求选择合适的模型。训练模型:使用历史数据训练模型,并根据评估指标来调整......
  • 【C++学习笔记 16】构造函数初始化列表
    当编写类并向其中添加成员时,通常需要某种方式对这些成员进行初始化。常见的方法,如写一个构造函数赋初值classEntity{private: std::stringm_Name;public: Entity(){ m_Name="UnKnow"; } Entity(conststd::string&name){ m_Name=name; } constst......
  • 【WSN覆盖优化】基于鱼鹰优化算法OOA求解无线传感器节点2D覆盖优化问题附Matlab代码
    鱼鹰优化算法(OspreyOptimizationAlgorithm,OOA)是一种基于鱼鹰捕鱼行为的启发式优化算法,可用于解决优化问题。在无线传感器网络(WSN)中,覆盖优化是一个关键问题,涉及到最大化网络覆盖范围并减少节点数量。以下是一个简单的示例框架,展示如何基于OOA算法求解无线传感器节点的二......
  • 指针学习(1)(1)
    目录1.指针变量和地址1.1取地址操作符(&)1.2指针变量1.3拆解指针 1.4解引用操作符(*)1.5指针类型的大小1.6void*指针 2.const修饰指针2.1const修饰变量2.2const修饰指针变量2.2.1const在*左边2.2.2const在*右边  2.2.3const在*两侧 结论: 1.指针变量和地......