【刷题】双指针入门

简介: 经过这四道题目的洗礼,我大概对双指针有了初步印象,接下来我会继续努力!!!


双指

双指针是非常经典的算法,包括但不限于前后双指针,快慢双指针,特殊双指针

尤其需要注意的是双指针并不能只局限于指针,数组下标,过程数据都可以成为“指针”。重要的是能够灵活使用双指针的思想,把解题思路捋顺

下面,我们来会会几道双指针的题目:

283.移动零

家人们 !!! 上连接:283.移动零

通过题目,发现这并不是一到很复杂的题。主要难点在于不改变数组的相对顺序。

这里我们使用前后双指针,逐渐遍历完成操作:

  1. 首先定义两个数组下标 i j
  2. 我们赋予他们不同含义:

[ 0 ,i)是已经处理过,已经没有零的部分 并按相对顺序排好
[i , j] 是零的部分
(j , n) 待处理的部分

  1. 我们控制 j 来进行整个数组的遍历,0 到 i是非零数据。
  2. 遇到 0 ,i j 位置互换即可

    来看代码:(类似冒泡排序的过程,把零向后挪动)
class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        for(int i = 0,j = 0;j<nums.size();j++)
            if(nums[j] != 0) swap(nums[j],nums[i++]);
    }
};

非常简洁的代码。就可以完成我们的操作。来看效果:

很好!过啦!!!!

1089. 复写零

家人们!!!跟上节奏:1089. 复写零

这道题与前面的移动零很像,但使用的算法细节不同。

这里需要的也是双指针 i j:

  1. 首先定义两个数组下标 i j
  2. 赋予他们不同含义:
    0 到 i 是处理完的部分
    i 到 j 是 未处理部分
  3. 首先使用 i 遍历整个数组,j 负责调换未处理的数据(将数据后移,空出新的零的位置)

    来看代码:
class Solution {
public:
    void duplicateZeros(vector<int>& arr) {
        for(int i = 0;i<arr.size();i++){
            if(arr[i] == 0){
                for(int j = arr.size() - 1 ; j > i ; j--){
                    arr[j] = arr[j - 1];
                }
                ++i;
            }
        }

    }
};

运行效果:

202. 快乐数

家人们!!! 继续干:202. 快乐数

这道题是比较特殊的一道题,我们来看奥:

首先看测试用例的 1 9 和 2 ;

可以发现最后都会处于循环:这里可以证明一下为什么都会处于循环:

假设我们最大数为 99999 99999 那对应的数为 810 ,相当于 0 到 9999999999 只有 810 个数与之对应,所以必然会出现循环。

到这里,大家应该也看出这和判断链表是否有环很像,使用快慢指针,慢指针依次进行一步操作,快指针一次两步操作。这里“指针”代指数字。


class Solution {
public:
  //操作函数
    int getsum(int n ){
        int sum = 0;
        while(n){
            int i = n % 10;
            sum += i*i;
            n /= 10;
        }
         return sum;
        }

    bool isHappy(int n) {
    //初始化
        int slow = n;
        int fast = getsum(n);
    //进行循环 直到相遇
        while(slow != fast){
            slow = getsum(slow);
            fast = getsum(getsum(fast));
           
        }
        //判断一下即可
        if(slow == 1) return true;
        return false;

    }
};

来看效果:

很好! 过啦!!!!

11. 盛最多水的容器

家人们,终于到了最后一题: 11. 盛最多水的容器

这道题可谓十分抽象:

这里使用前后双指针,代我细细到来为什么:

首先我们选取前后这一片段,然后得到一个体积值。

这时我们可以进行一下分析:

  1. 如果移动较大这边的指针,那长必然减小 , 高一定不会增加所以不需移动较高这边
  2. 再来看较小这边,移动后不能确定到底是增加还是减少,所以需要移动进行遍历

根据这两条规矩我们就可以完成操作:来看图解(来自 力扣官方题解)

这样必然可以得到答案。

class Solution {
public:

    int maxArea(vector<int>& height) {
        int i = 0;
        int j = height.size() - 1;
    // 记录答案值
        int ans = 0;
        while(i != j){
          //求得新的体积
            int v = min(height[i],height[j]) * (j - i);
            //取最大值
            ans = max(ans,v);
            // 移动较小的指针
            if(height[i] < height[j])
                i++;
            else
                j--;

        }
        return ans;
    }
};

来看效果:

过啦!!!(还存在改进空间)

经过这四道题目的洗礼,我大概对双指针有了初步印象,接下来我会继续努力!!!

Thanks♪(・ω・)ノ谢谢阅读!!!

下一篇文章见!!!

相关文章
|
6月前
|
算法 容器
OJ刷题日记:2、双指针(2)
OJ刷题日记:2、双指针(2)
40 0
|
25天前
|
存储 编译器 C语言
C++入门2——类与对象1(类的定义和this指针)
C++入门2——类与对象1(类的定义和this指针)
21 2
|
3月前
|
存储 安全 编译器
C++入门 | auto关键字、范围for、指针空值nullptr
C++入门 | auto关键字、范围for、指针空值nullptr
62 4
|
3月前
|
Python
【Leetcode刷题Python】138. 复制带随机指针的链表
LeetCode上题目“138. 复制带随机指针的链表”的Python解决方案,包括两种方法:一种是在每个节点后复制一个新节点然后再分离出来形成新链表;另一种是构建一个字典来跟踪原始节点与其副本之间的映射关系,从而处理新链表的构建。
20 1
|
3月前
|
Go 计算机视觉
Go从入门到放弃之指针
Go从入门到放弃之指针
|
4月前
|
存储 安全 编译器
【C++入门 四】学习C++内联函数 | auto关键字 | 基于范围的for循环(C++11) | 指针空值nullptr(C++11)
【C++入门 四】学习C++内联函数 | auto关键字 | 基于范围的for循环(C++11) | 指针空值nullptr(C++11)
|
4月前
|
算法 Java C语言
刷题训练之双指针问题
刷题训练之双指针问题
27 0
|
6月前
入门后指针进阶习题深度分析
入门后指针进阶习题深度分析
38 1
|
6月前
|
算法 测试技术 容器
【刷题】双指针进阶
请看入门篇 :双指针入门
31 0
【刷题】双指针进阶
|
6月前
|
算法
"刷题记录:哈希表+双指针 | leetcode-2465. 不同的平均值数目 "
该文段是一篇关于编程题目的解答,主要讨论如何找到数组中所有不同平均值的个数。作者首先使用排序和哈希集来解决,将数组转为列表排序后,通过双指针计算平均值并存入哈希集以去重。然后,作者发现可以优化方案,通过双指针在排序后的数组中直接计算两数之和,用哈希集记录不重复的和,从而避免实际计算平均值,提高了算法效率。最终代码展示了这两种方法。
51 0