首页 > 编程语言 >我爱学算法之—— 感受双指针带来的快感(下)

我爱学算法之—— 感受双指针带来的快感(下)

时间:2024-12-13 15:28:42浏览次数:8  
标签:right nums int 算法 我爱学 指针 快感 left

前言

本篇文章继续来学习双指针算法;继续加油!!!

一、三数之和

15. 三数之和 - 力扣(LeetCode)

题目解析

在这里插入图片描述

题目要求我们在一个给定的数组中,找到和等于0的三元组;但是呢有一些要求

  • 首先,这三元组中的元素是给定数组中的不同元素
  • 其次,找到的三元组不能够重复

算法分析

暴力枚举+set去重

首先,看到题目第一想到的是暴力枚举,枚举出所有的三元组,找到和为0的,然后再进行去重操作。

利用双指针优化

当然,枚举所有三元组这样解法,时间复杂度为O(n^3);而且去重操作也不简单,现在来优化一下。

我们这里借用两数之和中利用双指针算法找和为target的思路;依次固定(从左到右)给定数组中的数字i,然后利用双指针算法,在其右边区间内找到和为-i的两个数,找到返回即可。

细节处理

  • 去重:对于去重操作,这里也不使用set去重(代价有些大);直接让数组有序,在遍历数组时就直接跳过重复元素。
  • 查找的三元组完全:对与这个问题,我们在利用双指针算法找到满足要求的数之后,让双指针继续遍历而不是直接结束即可。

过程分析

代码实现

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> ret;
        //让数组有序
        sort(nums.begin(),nums.end());
        int n = nums.size();
        for(int i=0;i< n-2 &&nums[i]<=0;)
        {
            int left = i+1,right = n-1;
            int target = -nums[i];
            while(left<right)
            {
                int sum = nums[left] + nums[right];
                if(sum >target)
                    right--;
                else if(sum < target)
                    left++;
                else
                {
                    ret.push_back({nums[i],nums[left++],nums[right--]});
                while(left<right && nums[left] == nums[left-1])
                    left++;
                while(left<right && nums[right] == nums[right+1])
                    right--;
                }
            }
            i++;
            while(i<n-2 && nums[i] == nums[i-1])
                i++;
        }
        return ret;
    }
};

部分代码解释:

  • 首先,固定一个数的循环中,没有在for循环中执行i++是因为,在跳过重复元素的时候,已经指向完++了。
  • 其次,双指针算法找到满足条件的元素后,没有直接跳出,而是跳过重复元素继续遍历。

二、四数之和

18. 四数之和 - 力扣(LeetCode)

题目解析

在这里插入图片描述

题目要求我们在给定数组中,找到和为target的四元组。

  • 首先,四元组中的四个元素不能重复;
  • 其次,四元组不能重复

算法分析

思路:

首先,肯定是暴力枚举+去重;(不多说)

在其上进行优化;我们可以故技重施,借用一下三数之和的思想,来解决

  • 从左到右固定一个数,在其右边区间寻找三数之和为target-a的(a为固定的数)
  • 寻找三叔之和,从左到右固定一个数,在其右边区间寻找两数之和为target-a-bb为第二次固定的数)。
  • 利用双指针算法寻找两数之和。

思路在这里了(个人感觉就是问题化繁为简)。

这里就不进行过程分析了,其过程就和三数之和过程类似。

代码实现

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 i=0;i<n;)
        {
            for(int j = i+1;j<n;)
            {
                long long x = (long long)target - nums[i] - nums[j];
                int left=j+1,right= n-1;
                while(left < right)
                {
                    int sum = nums[left] + nums[right];
                    if(sum > x)
                        right--;
                    else if(sum < x)
                        left++;
                    else
                    {
                        ret.push_back({nums[i],nums[j],nums[left++],nums[right--]});
                        while(left < right && nums[left] == nums[left - 1])
                            left++;
                        while(left < right && nums[right] == nums[right + 1])
                            right--;
                    }
                }
                ++j;
                while(j<n && nums[j] == nums[j - 1])
                    ++j;
            }
            ++i;
            while(i < n&& nums[i] == nums[i - 1])
            ++i;
        }
        return ret;
    }

};

双指针算法总结

通过学习双指针算法,明显能够感受到双指针算法的优势和其适用场景

  • 首先,就是能够在暴力解法的基础上,将时间复杂度降低一个维度;
  • 其次,双指针算法就适合在数组划分和数组有序时使用;
  • 最后,双指针算法使用起来十分便捷;还是非常重要的。

我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=2oul0hvapjsws

标签:right,nums,int,算法,我爱学,指针,快感,left
From: https://blog.csdn.net/LH__1314/article/details/144412619

相关文章

  • 江科大STM32学习:01 C语言(2)指针
    1.指针简介指针Pointer是C语言的一个重要知识点,使用灵活,功能强大指针和底层硬件联系紧密(寄存器),使用指针可操作数据的地址,实现数据的间接访问2.计算机存储机制每个区域都是一个字节,线性分配下去,每个字节对应一个地址。注:一个字节是8bitinta=0x12345678;//十六进制,八......
  • 一篇搞懂c指针
    1、int*p//定义一个指向整型的指针;2、void(*fun)(void);//定义一个函数指针fun(函数的参数为任意类型,返回值为任意类型)。指向函数的指针double*fun(double*p);//声明一个函数fun,函数参数为指向double的指针,函数的返回值也是指向double的指针。3、int(*num[10])(inta);//......
  • C语言:指针(2)
    字符数组和字符指针字符串的实现在C语言中,表示一个字符串有以下两种形式:用字符数组存放一个字符串,用字符指针指向一个字符串案例:/***字符串的两种实现方式*/ //方式1:使用字符数组实现字符串 charstr[]="ILOVRYOU"; printf("%s\n",str); //使用字符指针实现字......
  • 十九、初识指针(2)
    指针不知道初始化为何值时,可先初始化为空指针。int*p=NULL;    //NULL,用来初始化指针,给指针赋值。一、指针运算1.指针+/-整数2.指针-指针|指针-指针|=中间的元素个数+1(同一数组)(同一块空间内存)(高地址-低地址)#define_CRT_SECURE_NO_WARNING......
  • C语言(函数指针与指针函数)
    函数指针定义:函数指针本质上是指针,它是函数的指针(定义了一个指针变量,变量中存储了函数的地址)。函数都有一个入口地址,所谓指向函数的指针,就是指向函数的入口地址。这里函数名就代表入口地址。函数指针存在的意义:让函数多了一种调用方式函数指针作为形参,可以形式调用(回调......
  • C语言(指针数组和数组指针)
    变量指针与指针变量指针变量指向数组通过指针引用数组元素引用一个数组元素,可以用:下标法:如a[i]形式。指针法:如*(a+i)*(p+i)。其中a是数组名,p是指向数组元素的指针变量,其初值:p=a;案例需求:有一个整型数组a,有10个元素。输出数组中的全部元素。分析:要输出各元素的值,有三......
  • (nice!!!)(LeetCode 热题 100) 76. 最小覆盖子串(哈希表、滑动窗口、双指针)
    题目:76.最小覆盖子串思路:用哈希表来记录字符串t中字符出现的情况。然后用双指针来实现滑动窗口,找到最小的字符串即可。时间复杂度为0(m+n),细节看注释。classSolution{public:stringminWindow(strings,stringt){ //哈希表unordered_map<char......
  • Go指针进阶:从入门到被虐,90%开发者都踩过这些坑
    Go指针进阶:从入门到被虐,90%开发者都踩过这些坑!原创 瀛洲在线编程之道 黑客编程之道  2024年11月17日21:10 吉林 听全文黑客编程之道分享黑客编程技术,Go、Python、Rust、Java等编程技术166篇原创内容公众号指针是Go语言中最强大但也最容易出错的特......
  • cpp智能指针
      普通指针的不足new和new[]的内存需要用delete和deletel]释放。程序员的主观失误,忘了或漏了释放。程序员也不确定何时释放。普通指针的释放类内的指针,在析构函数中释放。C++内置数据类型,如何释放?new出来的类,本身如何释放?C++11新增三个智能指针类型uniqu......
  • 善于运用指针--通过指针引用数组
    一个数组包含若干个元素,每个元素在内存中占用储存单元,它们都有相应的地址,指针变量能指向变量,也可以指向地址。所谓数组元素的地址,也就是数组元素的指针。文章目录前言一、在引用数组元素时指针的运算二、通过指针引用数组元素三、用数组名作函数参数1用指针打印数组2.指......