算法练习:双指针

news/2024/10/21 3:44:16/

目录

  • 1. 双指针
    • 1.1 移动 "0"
    • 1.2 复写 "0"
    • 1.3 快乐数(快慢指针)
    • 1.4 盛水最多的容器(单调性原则)
    • 1.5 有效三角形个数
    • 1.6 两个数之和
    • 1.7 三数之和
    • 1.8 四数之和

1. 双指针

1.1 移动 “0”

  1. 题目信息:
    在这里插入图片描述
  2. 题目链接:
    移动 “0”

思路演示:
在这里插入图片描述

补充:

  1. [0, dest]区间内的元素都为0
  2. [dest + 1, cur]区间内的元素都不为0
  3. cur指针遍历完数据,调整结束
class Solution 
{
public:void moveZeroes(vector<int>& nums) {int dest = -1;int cur = 0;while(cur < nums.size()){if(nums[cur]){swap(nums[cur], nums[++dest]);}cur++;}}
};

1.2 复写 “0”

  1. 题目信息:
    在这里插入图片描述
  2. 题目链接:
    复写"0"

思路演示:
在这里插入图片描述
在这里插入图片描述

注意:

  1. 寻找最后未覆盖结点时可能回导致dest越界,从而导致逆向复写的过程中出现越界错误。
    例:[0, 0, 0]
    因此,需要对此种越界情况做特殊处理。
class Solution 
{
public:void duplicateZeros(vector<int>& arr) {//找结点int cur = -1;int dest = -1;int size = arr.size();while (dest < size - 1){cur++;if (arr[cur] == 0){dest += 2;}else{dest++;}}//越界可能while(cur >= 0){if(arr[cur] == 0){//特殊处理if(dest > size - 1){arr[--dest] = arr[cur];}else{arr[dest] = arr[cur];arr[--dest] = arr[cur];}}else{//特殊处理if(dest > size - 1){arr[--dest] = arr[cur];}else{arr[dest] = arr[cur];}}dest--;cur--;}}
};

1.3 快乐数(快慢指针)

  1. 题目信息:
    在这里插入图片描述
  2. 题目链接:
    快乐数

过程演示:
在这里插入图片描述

注: 无论数n是否为快乐数,其进行快乐数的判断逻辑一定都会进入一个循环。我们将每次运算得出的结果视为结点,平方和的运算步骤视为链表的一步。那么,上述问题就可以理解为链表循环问题。(是否为只有1的环)

class Solution 
{
public:int gethappy(int num){int sum = 0;while(num){sum += (num % 10) * (num % 10);num /= 10;}return sum;}bool isHappy(int n) {//环状链表,快慢指针int quick = n;int slow = n;do{//快慢指针//走一步slow = gethappy(slow);//走两步quick = gethappy(quick);quick = gethappy(quick);}while(slow != quick);if(slow == 1){return true;}return false;}
};

1.4 盛水最多的容器(单调性原则)

  1. 题目信息:
    在这里插入图片描述
  2. 题目链接:
    盛水最多的容器

过程演示:

思路1:求出所有的容积,然后在其中选出最大(暴力求解)

思路2:单调性原则

在这里插入图片描述

  1. 容器的的高是由短边决定的
  2. 因此可以确定在高不变的情况下,移动长边只会导致底变短
  3. 所以可以确定当前的搭配是以短边为高一组中,容积最大的

只需记录每组中最大的容积,算法时间复杂度优化为O(n)

class Solution {
public:int maxArea(vector<int>& height) {//单调性原则//将小边丢掉int left = 0;int right = height.size() - 1;vector<int> area;while(left < right){if(height[left] < height[right]){area.push_back((right - left) * height[left]);left++;}else{area.push_back((right - left) * height[right]);right--;}}int max = area[0];for(auto e : area){if(e > max){max = e;}}return max;}
};

1.5 有效三角形个数

  1. 题目信息:
    在这里插入图片描述
  2. 题目链接:
    有效三角形个数
  3. 思路:
    <1> 先将所给数组进行排序(升序)
    <2> 判断三个数是否能够组成三角形的三个边:任意两边之和大于第三边
    <3> 指针对撞法(优化暴力求解)

过程演示:
在这里插入图片描述

class Solution 
{
public:int triangleNumber(vector<int>& nums) {//任意两边之和大于第三边//优化先排序再判断sort(nums.begin(), nums.end());int times = 0;int count = nums.size() - 1;int left = 0;int right = count - 1; while(count >= 2){while(right >= 1){while(left < right && nums[right] + nums[left] <= nums[count]){left++;}if(left < right){times += (right - left);}right--;}left = 0;count--;right = count - 1;}return times;}
};

1.6 两个数之和

  1. 题目信息:
    在这里插入图片描述
  2. 题目链接:
    两数之和
  3. 思路:
    <1> 若两数之和大于等于指定数,移动右指针
    <2> 若两数之和小于指定数,移动左指针
    直至两指针相撞

过程演示:
在这里插入图片描述

class Solution 
{
public:vector<int> twoSum(vector<int>& price, int target) {vector<int> goods;//大挪右,小挪左int left = 0;int right =price.size() - 1;while(left < right && price[left] + price[right] != target){if(price[left] + price[right] > target){right--;}if(price[left] + price[right] < target){left++;}}if(left < right){goods.push_back(price[left]);goods.push_back(price[right]);}return goods;}
};

1.7 三数之和

  1. 题目信息:
    在这里插入图片描述
  2. 题目链接:
    三数之和
  3. 思路:
    <1> 将整个数组排序,固定一个数num,创建两个指针left(最左则)与right(固定数num的前一个元素)
    <2> 左右指针开始遍历数组,arr[left] + arr[right] < num,left指针右移,arr[left] + arr[right] > num,right指针左移,当arr[left] + arr[right] > num时,记录此次搭配。重复遍历步骤,直至left >= right,结束此次遍历
    <3> 重复步骤2,直至num < 2

过程演示:
在这里插入图片描述

class Solution 
{
public:vector<vector<int>> threeSum(vector<int>& nums){//排序//去重//单调性vector<vector<int>> v1;sort(nums.begin(), nums.begin() + nums.size());int cur = nums.size() - 1;int right = 0;int left = 0;while (cur > 1){right = cur - 1;left = 0;//一次遍历while (right > left){//判断同时去重if ((right < cur - 1 && nums[right] == nums[right + 1]) || nums[right] + nums[left] > -nums[cur]){right--;}else if ((left > 0 && nums[left] == nums[left - 1]) || nums[right] + nums[left] < -nums[cur]){left++;}else{//记录vector<int> v2;v2.push_back(nums[left]);v2.push_back(nums[right]);v2.push_back(nums[cur]);v1.push_back(v2);right--;}}//去重do{cur--;} while (cur > 1 && nums[cur] == nums[cur + 1]);}return v1;}
};

1.8 四数之和

  1. 题目信息:
    在这里插入图片描述
  2. 题目链接:
    四数之和
  3. 思路:在三指针的基础上再套一层
  4. 注:int类型存在数据溢出的风险
class Solution
{
public:vector<vector<int>> fourSum(vector<int>& nums, int target){sort(nums.begin(), nums.end());vector<vector<int>> vv;int end = nums.size() - 1;int a = 0;while (end - a + 1 >= 4){int b = a + 1;while (end - b + 1 >= 3){int left = b + 1;int right = end;while (left < right){int sum = nums[left] + nums[right];long long goal = (long long)target - nums[a] - nums[b];//去重if ((right < end && nums[right + 1] == nums[right]) || sum > goal){right--;}else if ((left > b + 1 && nums[left - 1] == nums[left]) || sum < goal){left++;}else{vector<int> v;v.push_back(nums[a]);v.push_back(nums[b]);v.push_back(nums[left]);v.push_back(nums[right]);vv.push_back(v);left++;}}do{b++;} while (end - b + 1 >= 3 && nums[b - 1] == nums[b]);}do{a++;} while (end - a + 1 >= 4 && nums[a - 1] == nums[a]);}return vv;}
};

http://www.ppmy.cn/news/1372575.html

相关文章

重构、重构、不小心把截图弄掉了,又要重新⏲

这里卡了一天的命令行了&#xff0c;都是vue,react的&#xff0c;也是服了。 参考文章&#xff0c;vue的响应式&#xff0c;以下是链接 https://blog.csdn.net/jieyucx/article/details/134534625 #mermaid-svg-H5Ltjf334Cx7lPuR {font-family:"trebuchet ms",verda…

uniapp实现---类似购物车全选

目录 一、实现思路 二、实现步骤 ①view部分展示 ②JavaScript 内容 ③css中样式展示 三、效果展示 四、小结 注意事项 一、实现思路 点击商家复选框&#xff0c;可选中当前商家下的所有商品。点击全选&#xff0c;选中全部商家的商品 添加单个多选框&#xff0c;在将多选…

嵌入式学习第二十五天!(网络的概念)

网络&#xff1a; 可以用来&#xff1a;数据传输、数据共享 1. 网络协议模型&#xff1a; 1. OSI协议模型&#xff1a; 应用层实际收发的数据表示层发送的数据是否加密会话层是否建立会话连接传输层数据传输的方式&#xff08;数据包&#xff0c;流式&#xff09;网络层数据的…

mongodb备份脚本

mongodb备份脚本参考:根据自己实际情况进行修改 cat /usr/local/mcs8/mongodb/dbbak.sh #!/bin/bash #!/usr/bin/bashbasePath=$(cd `dirname $0`; pwd)#获取当前系统时间 DATE=`date +%Y_%m_%d_%H%M%S`#备份存放路径 DIR_DATE=`date +%Y_%m_%d` TAR_DIR=$basePath/bak/lis…

适用于ZigBee应用的JN5168/001K、JN5188HN、JN5188THN/001Z、JN5189THN超低功耗射频微控制器MCU

一、JN5168/001K 适用于ZigBee应用的超低功耗、高性能无线微控制器 JN5168是超低功耗、高性能无线微控制器&#xff0c;适用于ZigBee应用&#xff0c;它具有256kB嵌入式闪存、32 kB RAM&#xff0c;无需外部存储器即可进行OTA升级。32位RISC处理器可通过不同宽度指令、多级指令…

25.基于springboot + vue实现的前后端分离-停车管理系统(项目 + 论文)

项目介绍 本停车场管理系统是中小型的停车场管理的系统。包括用户信息管理&#xff0c;车位信息管理&#xff0c;车位费用管理&#xff0c;停泊车辆管理&#xff0c;车辆进出管理等主要功能。为方便用户可以清晰地了解到车辆运行情况&#xff0c;可以通过本系统日历图形报表和柱…

Linux操作系统的vim常用命令和vim 键盘图

在vi编辑器的命令模式下&#xff0c;命令的组成格式是&#xff1a;nnc。其中&#xff0c;字符c是命令&#xff0c;nn是整数值&#xff0c;它表示该命令将重复执行nn次&#xff0c;如果不给出重复次数的nn值&#xff0c;则命令将只执行一次。例如&#xff0c;在命令模式下按j键表…

CSS浮动的使用与清除,web前端开发发展趋势

css盒模型 1&#xff0c;css盒模型基本概念&#xff1f; 2&#xff0c;标准模型和IE模型的区别&#xff1a;计算高度和宽度的不同&#xff0c;怎么不同&#xff0c;高度宽度是怎么计算的&#xff1f; 3&#xff0c;css如何设置这两种模型&#xff1f; 4&#xff0c;js如何设置…