【算法练习】双指针

news2025/1/13 13:31:17

目录

  • 移动零
  • 复写零
  • 快乐数
  • 盛最多水的容器
  • 有效三角形的个数
  • 和为s的两个数
  • 三数之和
  • 四数之和

移动零

在这里插入图片描述

算法原理:
数组划分(数组分块)

在这里插入图片描述
两个指针作用:
cur:从左到右扫描数组,遍历数组
dest:已处理的区间内,非零元素的最后一个位置

三个区间:
[0.dest]:已经处理过的非零元素
[dest+1, cur-1]:处理过的零元素
[cur,n-1] :待处理元素

情况1:当cur遇到0元素的时候,直接让cur向后移动一位
在这里插入图片描述
在这里插入图片描述

情况2:当cur遇到非零元素的时候,dest往后一位。然后交换这两个位置的元素,然后cur+1
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

情况3:当cur遍历到n时,就完成了区间的划分
在这里插入图片描述

总结:
cur从前往后遍历的过程中:
1.遇到0元素:cur元素++
2.遇到非零元素:
swap(dest+1,cur);
dest++,cur++;

代码

class Solution {
    public void moveZeroes(int[] nums) {
        for(int cur = 0, dest = -1; cur < nums.length; cur++) {
            if(nums[cur] != 0) {
                dest++; 
                int tmp = nums[cur];
                nums[cur] = nums[dest];
                nums[dest] = tmp;
            }
        }
    }
}

复写零

在这里插入图片描述

算法原理:
解法:双指针算法
先根据“异地”操作,然后优化成双指针下的“就地”操作
异地操作就是说开辟一个新的数组,定义一个指针指向原始数组,定义一个新指针指向新数组,然后进行操作。
就地操作,就是把两个指针定义在同一个数组上。

1.先找到最后一个“复写”的数;
双指针算法:
1)先判断cur位置的值
2)决定dest向后移动一步或者两步
3.)判断一下dest是否已经到结束为止
4)cur++
1.5. 处理一下边界情况
n-1 -> 0
cur–
dest -=2
2.“从后向前”完成复写操作;

代码

public static void duplicateZeros(int[] arr) {
        int cur = 0, dest = -1, n = arr.length;
        // 1. 先找到最后一个需要复写的数
        while (cur < n) {
            if (arr[cur] == 0) dest += 2;
            else dest += 1;
            if (dest >= n - 1) break;
            cur++;
        }
        // 1.5 处理一下边界情况
        if (dest == n) {
            arr[n - 1] = 0;
            cur--;
            dest -= 2;
        }
        // 2. 从后向前完成复写操作
        while (cur >= 0) {
            if (arr[cur] != 0) arr[dest--] = arr[cur--];
            else {
                arr[dest--] = 0;
                arr[dest--] = 0;
                cur--;
            }
        }
    }

快乐数

在这里插入图片描述

算法原理:
判断链表是否有环
在这里插入图片描述

解法:快慢双指针
1.定义快慢指针
2.慢指针每次向后移动一步,快指针每次向后移动两步
3.判断相遇时候的值即可

代码

class Solution {
    public int bitSum(int n) { // 返回n这个数每一位上的平方和
        int sum = 0;
        while (n != 0) {
            int t = n % 10;
            sum += t * t;
            n /= 10;
        }
        return sum;
    }

    public boolean isHappy(int n) {
        int slow = n;
        int fast = bitSum(n);
        while (slow != fast) {
            slow = bitSum(slow);
            fast = bitSum(bitSum(fast));
        }
        return slow == 1;
    }
}

盛最多水的容器

在这里插入图片描述

解法思路:
解法一:暴力枚举O(N^2)
解法二:利用单调性,使用双指针解决问题O(N)

代码

public int maxArea(int[] height) {
        int left = 0;
        int right = height.length - 1;
        int ret = 0;
        while (left < right) {
            int v = Math.min(height[left], height[right]) * (right - left);
            ret = Math.max(ret, v);
            if (height[left] < height[right]) left++;
            else right--;
        }
        return ret;
    }

有效三角形的个数

在这里插入图片描述

算法原理:
利用单调性,使用双指针算法来解决问题
先对整个数组排序。
先固定最大的数
在最大的数的左区间内,使用双指针算法,快速统计出符合要求的三元组的个数

代码

import java.util.Arrays;

public class Solution {
    public int triangleNumber(int[] nums) {
        // 1. 优化:排序
        Arrays.sort(nums);

        // 2. 利用双指针解决问题
        int ret = 0, n = nums.length;
        for (int i = n - 1; i > 0; 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的两个数

在这里插入图片描述

算法原理:
利用单调性,使用双指针算法解决问题

代码

public int[] twoSum(int[] nums, int target) {
        int left = 0, right = nums.length - 1;
        while (left < right) {
            int sum = nums[left] + nums[right];
            if (sum > target) right--;
            else if (sum < target) left++;
            else return new int[]{nums[left], nums[right]};
        }
        // 照顾编译器
        return new int[]{0};
}

三数之和

在这里插入图片描述

算法原理:
排序+双指针
1.排序;
2.固定一个数i
3.在该数后面的区间内,利用“双指针算法”,快速找到两个的和等于-i即可
处理细节:
1.去重 :找到一种结果之后,left和right指针要跳过重复元素;当使用完一次双指针算法之后,i也需要跳过重复元素
2.不漏 : 找到一种结果之后,不要”停“,缩小区间,继续寻找

代码

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {

        List<List<Integer>> ret = new ArrayList<>();
        // 1. 排序
        Arrays.sort(nums);

        // 2. 利于双指针解决问题
        int n = nums.length;
        for (int i = 0; i < n;) {//固定数 a
            if (nums[i] > 0) break;// 小优化
            int left = i + 1;
            int right = n - 1, target = -nums[i];
            while (left < right) {
                int sum = nums[left] + nums[right];
                if (sum > target) right--;
                else if (sum < target) left++;
                else {
                    // nums[i] nums[left] nums[right]
                    ret.add(new ArrayList<Integer>(Arrays.asList(nums[i], nums[left], nums[right])));
                    // 缩小区间,继续寻找
                    left++;
                    right--;
                    // 去重
                    while (left < right && nums[left] == nums[left - 1]) {
                        left++;
                    }
                    while (left < right && nums[right] == nums[right + 1]) {
                        right--;
                    }
                }
            }
            // 去重: i
            i++;
            while (i < n && nums[i] == nums[i - 1]) i++;
        }
        return ret;
    }
}

四数之和

在这里插入图片描述

算法原理:
排序+双指针
1.依次固定一个数a;
2.在a后面的区间内,利用“三数之和“找到三个数,使这三个数的和等于 target-a即可

代码

public List<List<Integer>> fourSum(int[] nums, int target) {

        List<List<Integer>> ret = new ArrayList<>();

        // 1. 排序
        Arrays.sort(nums);

        // 2. 利用双指针解决问题
        int n = nums.length;
        for (int i = 0; i < n; ) {// 固定数a
            // 三数之和
            for (int j = i + 1; j < n; ) {// 固定数 b
                // 双指针
                int left = j + 1, right = n - 1;
                long aim = (long)target - nums[i] - nums[j];
                while (left < right) {
                    int sum = nums[left] + nums[right];
                    if (sum > aim) right--;
                    else if (sum < aim) left++;
                    else {
                        ret.add(Arrays.asList(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;
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/756127.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

比Wi-Fi快100倍!Li-Fi无线传输标准802.11bb正式发布:带宽高达224GB/s

大家对Wi-Fi可以说耳熟能详&#xff0c;最新标准已经演进到802.11be&#xff0c;即Wi-Fi 7&#xff0c;理论速率可达30Gbps。 现在&#xff0c;更强的来了。 IEEE今日正式签署802.11bb无线传输标准&#xff0c;即Li-Fi&#xff0c;基于光波的无线传输。 Li-Fi支持者认为&#x…

Appium+python自动化(五)- 模拟器(超详解)

简介 Appium是做安卓自动化的一个比较流行的工具&#xff0c;对于想要学习该工具但是又局限于或许当前有些小伙伴没 android 手机来说&#xff0c;可以通过安卓模拟器来解决该问题&#xff0c;下面就讲解使用appium连接安卓模拟器的操作步骤。而宏哥是由于手机数据线问题&#…

【大数据Hive】Hive 内部表与外部表使用详解

目录 一、hive 内部表简介 1.1 查看内部表信息 二、hive 外部表简介 三、内部表与外部表对比 四、内部表与外部表操作演示 4.1 内部表操作 4.1.1 数据准备 4.1.2 建表sql 4.2 外部表操作 4.2.1 建表sql 4.2.2 上传数据文件到 /stu目录 4.2.3 内部表删除 4.2.4 外部…

【一蹴而就】软著申请时,如何更高效地将源码进行格式处理和合并呢?这篇博客告诉你答案。

【一蹴而就】软著申请时&#xff0c;如何更高效地将源码进行格式处理和合并呢&#xff1f;这篇博客告诉你答案。 1&#xff0c;软著申请三要素2&#xff0c;源代码合成软件SourceConvert2.1 启动文件2.2 Spring项目源代码格式2.2.1 规律的包名2.2.2 核心文件 3&#xff0c;Sour…

[QT编程系列-10]:C++图形用户界面编程,QT框架快速入门培训 - 4- QT画图与动画

目录 4. QT画图与动画 4.1 QT的绘图系统 4.2 案例目标 4.3 绘制过程 4.4 更换控件的icon 4.5 案例2 4.6 坐标轴 4. QT画图与动画 4.1 QT的绘图系统 QT&#xff08;也称为Qt Framework&#xff09;是一种流行的跨平台应用程序开发框架&#xff0c;它提供了丰富的图形用户…

网页无插件播放265/264视频/监控大屏/GPU解码

网页无插件播放265/264视频/监控大屏/GPU解码 先看效果 特点 GPU解码&#xff0c;chrome网页播放32路 h256/hevc 直播视频流,毫无压力。提供1分屏、4分屏、8分屏、9分屏、16分屏、32分屏、64分屏分屏切换不会停止播放GPU解码、无插件播放自动识别264/265&#xff0c;并且都是…

飞控学习笔记-梯度下降算法(gradient descent algorithm)

简介 笔记来源于文章&#xff1a;An_efficient_orientation_filter_for_inertial_and_inertial_magnetic_sensor_arrays 共轭&#xff1a; 四元数叉乘&#xff1a; 欧拉角等式&#xff1a;

vue-springboot美食商城网站的设计与实现0fh04

美食网站是在的数据存储主要通过MySQL。用户在使用应用时产生的数据通过Java语言传递给数据库。通过此方式促进美食信息流动和数据传输效率&#xff0c;提供一个内容丰富、功能多样、易于操作的平台。述了数据库的设计&#xff0c;系统的详细设计部分主要论述了几个主要模块的详…

一文阐明死锁的成因及解决方案

死锁是这样一种情形&#xff1a;多个线程同时被阻塞&#xff0c;它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期地阻塞&#xff0c;因此程序不可能正常终止。 目录 一、死锁的几种情况 1、一个线程&#xff0c;一把锁&#xff08;上面同一线程给同一对象加两…

stm32PID调参实验

使用了增量式PID,有点难调&#xff0c;数据一直在波动。实际中调参具有很大的不确定性&#xff0c;因为你这次调好了&#xff0c;下次再供电发现又不是那么回事。按照网上传统的调参方法&#xff0c;一般是先调P&#xff0c;I和D为0&#xff0c;逐渐增大P使得实际值快速到达目标…

【API生命周期看护】API监控与运维

一、基本概念 当接口完成发布、上线后&#xff0c;就进入了正常的运行与维护状态。此时&#xff0c;对于API本身的监控与运维则变得尤为重要&#xff0c;这是保障服务功能可用、SLA达成的重要手段。 监控与运维本身是一个非常大的概念&#xff0c;从DevOps这一词汇中也能看出…

Linux下做性能分析6:理解一些基础的CPU执行模型

[介绍] 前面介绍了两个典型的调度模型&#xff0c;如果调度没有问题&#xff0c;剩下的问题就是正面刚算法了。那个不是我这里要介绍的主题的。 但&#xff0c;Not Really。其实除了算法在消耗CPU&#xff0c;CPU还是有很多余力可以挖掘的&#xff0c;这一篇我们专门讨论一下…

MySQL “error: ‘fd’: 未知重写说明符”

文章目录 1、【问题】MySQL “error: ‘fd’: 未知重写说明符”2、【解决】增加引用头文件 1、【问题】MySQL “error: ‘fd’: 未知重写说明符” 有以下代码&#xff0c;mysql 的 include 和 lib 都已经加入附加目录&#xff0c;libmysql.lib 已经加入依赖库&#xff1a; #p…

IEEE ICME 2023论文|基于交互式注意力的语音情感识别联合网络

论文题目&#xff1a; A Joint Network Based on Interactive Attention for Speech Emotion Recognition 作者列表&#xff1a; 胡英&#xff0c;侯世静&#xff0c;杨华敏&#xff0c;黄浩&#xff0c;何亮 研究背景 语音情感识别&#xff08;Speech Emotion Recognitio…

4. MySQL 的增删查改(重点 9000字详解)

目录 准备工作 一、数据的插入 &#xff08;insert&#xff09; 注意 1. 整行插入 2. 指定列的插入&#xff08;常用&#xff09; 3. 一次插入多行数据 4. 清空数据库的数据&#xff08;truncate&#xff09; 5. 拓展练习&#xff1a;对于数据库中的数据进行统计&#…

多智能体强化学习(MARL)研究汇总:行为分析、通信学习、协作学习、智能体建模

【强化学习原理+项目专栏】必看系列:单智能体、多智能体算法原理+项目实战、相关技巧(调参、画图等、趣味项目实现、学术应用项目实现 专栏详细介绍:【强化学习原理+项目专栏】必看系列:单智能体、多智能体算法原理+项目实战、相关技巧(调参、画图等、趣味项目实现、学术应…

第一百零七天学习记录:C++核心:类和对象Ⅷ(五星重要)多态

多态 多态的基本概念 多态是C面向对象三大特性之一 多态分为两类 1、静态多态&#xff1a;函数重载 和 运算符重载属于静态多态&#xff0c;复用函数名 2、动态多态&#xff1a;派生类和虚函数实现运行时多态 静态多态和动态多态的区别&#xff1a; 1、静态多态的函数地址早绑…

Arthas的火焰图生成

之前说过用idea自带的工具生成火焰图&#xff0c;但是idea是在本地的&#xff0c;在机器上如何生成呢&#xff1f; 我觉得方法有很多&#xff0c;这里用arthas工具简单搞一搞 Arthas官网地址 下载Arthas 如果在机器上要下载整个包&#xff0c;arthas-boot.jar需要依赖其他的j…

上门按摩系统如何运营才能做大

预约上门按摩系统是一种在线平台或应用程序&#xff0c;用于帮助用户预约并安排专业按摩师上门提供按摩服务。这种系统通常为用户提供一个简便的方式来选择按摩服务类型、时间和地点&#xff0c;并与合适的按摩师进行预约。用户可以通过应用程序或网站浏览按摩师的资料和评论&a…

用googletest写cpp单测

框架概述 Google Test&#xff08;也称为 googletest&#xff09;是由 Google 开发的 C 单元测试框架。它的首个版本是在2004年发布的&#xff0c;作为 Google 内部的测试框架使用。随后&#xff0c;Google Test 在开源社区中得到广泛应用&#xff0c;并在许多项目和组织中成为…