优选算法的协作之舞:双指针专题(二)

优选算法的协作之舞:双指针专题(二)

专栏:算法

个人主页:手握风云

目录

一、算法例题

1.1. 复写零

1.2. 快乐数

1.3. 三数之和

1.4. 四数之和


一、算法例题

1.1. 复写零

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

 

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

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

完整代码实现:

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。

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向右移动时,如果指向的数不变,则继续向右移动。

完整代码实现:

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。寻找出的四元子数组依然是要不重不漏。

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; } }

Read more

remote: Invalid username or token. Password authentication is not supported for Git operations

remote: Invalid username or token. Password authentication is not supported for Git operations

remote: Invalid username or token. Password authentication is not supported for Git operations. fatal: Authentication failed for… 该文章解决在新系统中进行 git 操作时,第一次的登陆问题,由于Github不再支持使用账号密码进行 Git https 推送,可以采用 ssh 密钥的方式进行长期的推送 1.生成SSH key ssh-keygen -t ed25519 -C "[email protected]" 这里的-t 表示要生成的密钥类型,这里生成的类型为ed25519,是一种椭圆曲线算法,比传统的RSA更加安全、密钥更短,并且速度更快 2.将

By Ne0inhk

深度解析 GitHub Copilot Agent Skills:如何打造可跨项目的 AI 专属“工具箱”

前言 随着 GitHub Copilot 从单纯的“代码补全”工具向 Copilot Agent(AI 代理) 进化,开发者们迎来了更高的定制化需求。我们不仅希望 AI 能写代码,更希望它能理解团队的特殊规范、掌握内部工具的使用方法,甚至在不同的项目中复用这些经验。 Agent Skills(代理技能) 正是解决这一痛点的核心机制。本文将深入解析 Copilot Skills 的工作原理,并分享如何通过软链接(Symbolic Link)与自动化工作流,构建一套高效的个人及团队知识库。 一、 什么是 Agent Skills? 如果说 Copilot 是一个通用的“AI 程序员”,那么 Skill(技能) 就是你为它配备的专用工具箱。 它不仅仅是一段简单的提示词(Prompt),而是一个包含元数据、指令和执行资源的标准文件夹结构。当

By Ne0inhk

YOLO X Layout开源模型部署教程:从Docker拉取到Web服务上线全流程

YOLO X Layout开源模型部署教程:从Docker拉取到Web服务上线全流程 1. 这不是普通文档识别,而是真正能“读懂”排版的AI工具 你有没有遇到过这样的问题:手头有一堆扫描件、PDF截图或者手机拍的合同、报告、论文,想快速提取其中的表格数据,却要手动复制粘贴;想把一页PPT里的标题、正文、图片分别处理,结果发现传统OCR只管文字,完全不管结构;又或者在做自动化文档处理系统时,卡在了“怎么让程序知道哪块是表格、哪块是图注、哪块是页眉”这个环节? YOLO X Layout就是为解决这类问题而生的。它不只识别文字,而是像人眼一样理解整页文档的视觉布局——看到一张图,立刻分清哪里是标题、哪里是正文段落、哪里是表格边框、哪里是公式、哪里是页脚小字。它把文档当成一幅画来分析,用目标检测的方式,给页面上每个有意义的区域打上精准标签。 更关键的是,它开箱即用。不需要你从零训练模型,不用配环境装依赖到崩溃,甚至不用写一行推理代码。本文会带你从最基础的Docker命令开始,一步步完成镜像拉取、模型挂载、服务启动,

By Ne0inhk

在github codespaces部署开源个人智能体OpenClaw(Clawdbot/Moltbot)使用教程

openClaw官方仓库:https://github.com/openclaw/openclaw OpenClaw 是什么? OpenClaw(原名 Clawdbot,后更名为 Moltbot,现正式命名为 OpenClaw)是一个运行在你本地环境的高权限 AI 智能体。它的核心特性包括: * 本地部署:运行在你的服务器或电脑上,数据完全自主可控 * 多平台支持:支持飞书、WhatsApp、Telegram、Discord、Slack 等主流聊天工具 * 浏览器控制:可以浏览网页、填写表单、提取数据 * 系统访问:读写文件、执行 Shell 命令、运行脚本 * 持久化记忆:记住你的偏好和上下文,成为真正属于你的 AI * 插件扩展:支持社区技能插件,甚至可以自己编写插件 无论是邮件管理、日程安排、数据查询还是代码编写,OpenClaw

By Ne0inhk