优选算法的灵动之章:双指针专题(二)

news/2025/3/27 11:45:45/


专栏:算法

个人主页:手握风云


目录

一、算法例题

1.1. 复写零

1.2. 快乐数

1.3. 三数之和

1.4. 四数之和


一、算法例题

1.1. 复写零

       题目要求我们要进行就地修改,并且函数不返回任何类型。我们先思考两个数组异地修改。我们同样是定义两个指针cur和dest。当cur指向非零元素时,dest直接照抄,然后统一向右移动一位;当cur指向零元素时,dest照抄两遍。

 

       我们接着对异地操作进行优化,然后再思考就地操作。如果cur指向零元素时,就会把下一个元素给覆盖掉,导致后面都会被复写成零,所以两个指针从前向后完成复写操作是错的。那我们就换一种思路,从后向前完成复写。

        由于题目要求不能超过原有数组的长度,所以我们首先要找到复写之后数组的最后一个元素。我们让cur指向非零元素,dest向右移动一位;如果cur指向零元素,dest向右移动两位。但此时还有一种特殊情况,如果复写之后最后一个元素为零,那么dest就会越界,所以我们还要单独处理一下边界,只需把倒数第二个元素直接复写成零,然后cur向前移动一位,dest向前移动两位。

完整代码实现:

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

1.2. 快乐数

        我们先要明白快乐数的定义。通过上图所示,要判断一个数是否是快乐数,就是判断一个链表是否有环,且环是否为1。我们之前已经在链表章节讲过类似的题目。定义一个快指针和一个慢指针。快指针一次走两步,慢指针一次走一步,最终两个指针一定会相遇。也就是我们要判断相遇点是否为1。

java">class Solution {public int HappySum(int 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 = HappySum(n);while(slow != fast){slow = HappySum(slow);fast = HappySum(HappySum(fast));}return slow == 1;}
}

1.3. 三数之和

        首先我们依然想到的是先排序,然后暴力枚举,利用三层for循环来判断三数之和是否为零,由于题目不要求输出的顺序和三元组的顺序,所以我们需要对三元组进行去重的操作,那么此时的时间复杂度就是O(n^{3})

        接着我们对解法进行优化,对于有序数组,我们可以想到二分查找或者是双指针。我们先固定第一个元素,然后从剩余的区间里面查找两数之和是否为被固定数字的相反数。查找两数之和,我们这里就不再多说。

       接下来是去重操作。我们先对三元子数组进行去重,当我们left或者是right移动一位所指向的值不变,那么就继续移动,此时我们需要注意指针是否会越界。然后对固定的数进行去重操作,i向右移动时,如果指向的数不变,则继续向右移动。

完整代码实现:

java">class Solution {public List<List<Integer>> threeSum(int[] nums) {List<List<Integer>> ret = new ArrayList<>();//第1步,排序Arrays.sort(nums);//第2步,双指针算法解决int len = nums.length;for (int i = 0; i < len;) {if(nums[i] > 0) break;int left = i+1, right = len-1, target = -nums[i];//利用查找两数之和的算法思想while(left < right){int sum = nums[left] + nums[right];if(sum < target) {left++;} else if (sum > target) {right--;} else if (sum == target) {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++;while(i<len && nums[i] == nums[i-1]) i++;}return ret;}
}

1.4. 四数之和

         这道题与三数之和的解法类似,同样对数组进行排序,先固定一个数a,再去寻找三数之和target - a,接着固定一个数b,再去寻找两数之和target - a - b。寻找出的四元子数组依然是要不重不漏。

java">class Solution {public List<List<Integer>> fourSum(int[] nums, int target) {List<List<Integer>> ret = new ArrayList<>();//第一步,排序Arrays.sort(nums);//利用双指针解决int len = nums.length;for (int i = 0; i < len; ) {//固定第一个数for (int j = i+1; j < len; ) {//固定第二个数int left = j+1,right = len-1;long aim = (long)target-nums[i]-nums[j];while(left < right){int sum = nums[left] + nums[right];if(sum < aim) left++;else if (sum > aim) right--;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<len && nums[j]==nums[j-1]) j++;}i++;while(i<len && nums[i]==nums[i-1]) i++;}return ret;}
}

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

相关文章

SpringBoot 统一功能处理之拦截器、数据返回格式、异常处理

目录 拦截器 一、什么是拦截器 二 拦截器的使用 三 拦截路径配置 四 拦截器的执行流程 统一数据返回格式 统一异常处理 拦截器 一、什么是拦截器 拦截器是Spring框架提供的核心功能之一&#xff0c;主要用来拦截用户的请求&#xff0c;在指定方法前后&#xff0c;根据业务…

【数据结构初阶第十节】队列(详解+附源码)

好久不见。。。别不开心了&#xff0c;听听喜欢的歌吧 必须有为成功付出代价的决心&#xff0c;然后想办法付出这个代价。云边有个稻草人-CSDN博客 目录 一、概念和结构 二、队列的实现 Queue.h Queue.c test.c Relaxing Time&#xff01; ————————————《有没…

计算机毕业设计PySpark+hive招聘推荐系统 职位用户画像推荐系统 招聘数据分析 招聘爬虫 数据仓库 Django Vue.js Hadoop

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

2025 年前端开发现状分析:卷疯了还是卷麻了?

一、前端现状&#xff1a;框架狂飙&#xff0c;开发者崩溃 如果你是个前端开发者&#xff0c;那么你大概率经历过这些场景&#xff1a; 早上打开 CSDN&#xff08;或者掘金&#xff0c;随便&#xff09;&#xff0c;发现又有新框架发布了&#xff0c;名字可能是 VueXNext.js 之…

腿足机器人之二- 运动控制概览

腿足机器人之二运动控制概览 高层运动规划MPCRL 中层逆运动学和逆动力学底层执行器控制传感器校正 上一篇博客是腿足机器人的骨架和关节的机械和电气组件&#xff0c;关节不仅需要通过机械设计实现复杂的运动能力&#xff0c;还必须通过电子组件和控制系统来精确控制这些运动。…

Docker的前世今生及安装与使用命令详解

在云原生时代&#xff0c;容器技术已经成为软件开发与部署的关键工具。其中&#xff0c;Docker 凭借其轻量、灵活和高效的特性迅速走红。本文将带你走进 Docker 的历史沿革&#xff0c;了解其从前世到今生的发展历程&#xff0c;并详细介绍如何安装 Docker 以及常用的操作命令。…

Django 创建表时 “__str__ ”方法的使用

在 Django 模型中&#xff0c;__str__ 方法是一个 Python 特殊方法&#xff08;也称为“魔术方法”&#xff09;&#xff0c;用于定义对象的字符串表示形式。它的作用是控制当对象被转换为字符串时&#xff0c;应该返回什么样的内容。 示例&#xff1a; 我在初学ModelForm时尝…

Ollama+DeepSeek+Open-WebUi

环境准备 Docker Ollama Open-WebUi Ollama 下载地址&#xff1a;Ollama docker安装ollama docker run -d \ -v /data/ollama/data:/root/.ollama \ -p 11434:11434 \ --name ollama ollama/ollama 下载模型 Ollama模型仓库 # 示例&#xff1a;安装deepseek-r1:7b doc…