LeetCode——双指针(初阶)

LeetCode——双指针(初阶)

文章目录

简要介绍

我们的双指针算法是算法题中比较常见的一种算法,常见的双指针实际上是有两种的,一种是对撞指针,一种就是我们的快慢指针。

对撞指针

一般用于我们的顺序结构当中,也叫左右指针。

实现思路:

1、对撞指针就是从序列两端向中间移动。

2、终止条件一般就是两个指针相遇了或是错开了。

快慢指针

这个指针又叫龟兔赛跑算法,就是使用两个移动速度不同的指针在序列上移动。常用于我们的环形链表或是数组中。

实现思路:

1、研究问题是不是有循环往复的现象出现。

2、设置一个快指针和一个慢指针,比如让快指针移动两步,慢指针移动一步。

相关例题

移动零

题目描述

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

请注意 ,必须在不复制数组的情况下原地对数组进行操作。

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

请注意 ,必须在不复制数组的情况下原地对数组进行操作。

示例 1:

输入: nums = [0,1,0,3,12] 输出: [1,3,12,0,0] 

示例 2:

输入: nums = [0] 输出: [0] 

提示:

  • 1 <= nums.length <= 104
  • -231 <= nums[i] <= 231 - 1

进阶:你能尽量减少完成的操作次数吗?

实现思路

版本一

这是我自己一开始想到的思路:

这个题的本质就是将我们的非零数放在数组的开头且顺序不能改变,而我们的零就要放在数组的尾端。所以可以先统计一下我们有几个非零的数,然后给一个指向开头的指针,遍历整个数组将我们的非零数一个一个的交换到我们的开头,同时我们的头指针向后移动直到我们的遍历完了非零数。

实现代码

classSolution{public:voidmoveZeroes(vector<int>& nums){int cnt =0;for(auto& s : nums){if(s ==0) cnt++;} cnt = nums.size()- cnt;int k =0;for(int i =0; i < nums.size(); i++){if(nums[i]!=0){swap(nums[i], nums[k++]);}if(k > cnt){break;}}}};
版本二

实际上上面这个代码非常的冗余,我们这里在实现的时候只需要设置一个头指针,然后将非零数直接向头位置替换即可,不需要计算什么个数。

实现代码

classSolution{public:voidmoveZeroes(vector<int>& nums){int cnt =0;for(int i =0; i < nums.size(); i++){if(nums[i]){swap(nums[i], nums[cnt++]);}}}};
最终版

我们上面的代码实际上就是实现的双指针,只是我们遍历的下标就是我们的一个指针罢了,为了体现我们的双指针思路,我们这里给出一个比较标准的流程。

首先我们要知道我们要有两个指针,一个指针cur用来扫描我们的整个数组,一个指针dest用来记录我们的非零序列的最后一个位置,于是根据题意我们遍历的时候[0, dest]的元素都是我们的非零元素,我们的[dest - 1, cur - 1]的元素都是零元素。

1、初始化我们的cur为0,dest = -1(指向空)。

2、使用cur遍历的时候会有两种情况:

a、遍历到了0,我们继续遍历即可(满足我们的[dest - 1, cur - 1]上面都是零元素)。

b、遍历到了非零,我们就++dest并且交换我们的cur位置和dest位置,继续遍历即可(满足[0, dest]的元素都是非零)。

实现代码

classSolution{public:voidmoveZeroes(vector<int>& nums){int n=nums.size();for(int i=0,cur=0,index=-1;i<n;i++){if(nums[i]){swap(nums[++index],nums[i]);}}}};

复写零

题目描述

给你一个长度固定的整数数组 arr ,请你将该数组中出现的每个零都复写一遍,并将其余的元素向右平移。

注意:请不要在超过该数组长度的位置写入元素。请对输入的数组 就地 进行上述修改,不要从函数返回任何东西。

示例 1:

输入:arr = [1,0,2,3,0,4,5,0] 输出:[1,0,0,2,3,0,0,4] 解释:调用函数后,输入的数组将被修改为:[1,0,0,2,3,0,0,4] 

示例 2:

输入:arr = [1,2,3] 输出:[1,2,3] 解释:调用函数后,输入的数组将被修改为:[1,2,3] 

提示:

  • 1 <= arr.length <= 104
  • 0 <= arr[i] <= 9

实现思路

版本一

算法题还是太奇妙了,之前写的思路看了好久才看懂写了什么(bushi) ,这里是我自己一开始想到的思路,思路历程如下:

1、其实我们这里比较中要的就是对于特殊情况的判断(一开始就是这里错了),我们要对复写的情况进行判断,这里有两种情况

第一种情况:

就是我们的所有的零都是可以复写,我们这里的情况还是很好理解的,就是示例中写的样子。

第二种情况:

这里也是比较容易忽略的情况,我们这里在示例一上面改进给出我们的图示:

2、我们这里的思路就是找到我们复写后数组的最后一个元素复写前的下标,这里我们实现的时候就是使用的我们的双指针算法,定义两个指针一个指针i用来遍历和找最后一个值的下标,一个指针cnt用来终止遍历,逻辑如下:

a、如果遍历到了0,那么我们cnt指针就++(表示需要复写),然后我们的i和cut指针都++。

b、如果遍历到的不是,那么我们就然i和cut++

3、经过了2步骤的遍历之后,我们的i -
1指向的就是我们要的最后一个值的下标,同时我们可以通过cut是不是等于n来判断是不是有我们第二种情况(cut等于n说明结果数组中的零都是复写了的,cut不等于n就是要大于n表示我们的第二种情况有一个零要超出范围)。

4、我们接下来就可以进行我们的数组复写操作了,我们这里从i - 1开始遍历,这里也是有两种情况:

a、如果遇到的是非零数或是我们上面第二种情况中绿色部分的数字,我们这个时候就将该值放在我们的数组后边,然后尾指针前移。

b、如果遇到的是零,我们就将两个零放在尾部。

实现代码

classSolution{public:voidduplicateZeros(vector<int>& arr){int n = arr.size();int cnt =0;int i =0;for(; i < n && cnt < n; i++, cnt++){if(arr[i]==0){ cnt++;}}bool flag =false;if(cnt == n){ flag =true;}int k = i -1;for(int j = k; j >=0&& n >=0; j--){if(arr[j]||(j == k &&!flag)){if(n >0) arr[--n]= arr[j];}else{if(n >0) arr[--n]=0;if(n >0) arr[--n]=0;}}}};
版本二

其实我们这里的版本二和我们的版本一并没有什么本质上的区别,只是在一些边界条件处理的地方有一些不同,实现思路如下:

1、初始化好两个指针cur = 0, dest = 0;

2、找到最后一个复写的数:

当cur < n的时候,执行下面的循环: a、判断cur位置的元素,如果是0的话,dest往后移动两位否则dest移动一位。

b、判断dest是不是到了结束的位置,是的话就结束循环,如果没有结束那么就cur++继续判断即可。

3、判断dest是不是已经越界了(也就是dest == n),如果是的话,我们n -
1位置的值就设置成为0,cur–,dest往前移动两步(和上面的不同就是这里是将我们的第二种情况直接单独考虑了,后续就不用管了)。

4、从cur位置往后开始遍历数组,然后复写出结果数组:

a、判断cur位置的值,如果是0的话,就在dest和dest - 1位置设置成0;不是0的话我们就直接给我们的cur位置的值即可。

b、cur–,开始下一个位置。

实现代码:

classSolution{public:voidduplicateZeros(vector<int>& arr){int cur=0,dest=-1,s=arr.size();while(cur<s){if(arr[cur]) dest++;else dest+=2;if(dest>=s-1)break; cur++;}if(dest==s){ arr[s-1]=0; dest-=2; cur--;}while(cur>=0){if(arr[cur]) arr[dest--]=arr[cur--];else{ arr[dest--]=0; arr[dest--]=0; cur--;}}}};

Read more

深度解析英伟达最新“瓦力”机器人:物理AI时代的开发者红利与技术突破

深度解析英伟达最新“瓦力”机器人:物理AI时代的开发者红利与技术突破

2026年CES展会上,黄仁勋牵着那款酷似《机器人总动员》“瓦力”的Reachy Mini机器人完成流畅互动时,全场的欢呼不仅是对萌系设计的认可,更是对一个新时代的致敬——英伟达用这套全新机器人系统,正式宣告物理AI从实验室走向产业化。对于咱们ZEEKLOG的开发者而言,这波技术浪潮带来的不只是视觉震撼,更是可落地的开发工具、开源生态和商业机遇。今天就从技术内核、开发价值、行业对比三个维度,深度拆解英伟达最新机器人的核心竞争力,帮大家找准入局切入点。 一、不止“萌出圈”:英伟达新机器人的技术内核拆解 很多人被“瓦力”的外形圈粉,但真正让行业震动的是其背后的全栈技术体系。不同于传统机器人“硬件堆砌+单一功能编程”的模式,英伟达这套系统是“大脑-身体-训练场”的全链路协同,每一个环节都为开发者预留了创新空间。 1. 核心大脑:GR00T N1.6模型的双系统突破 作为全球首个开源人形机器人基础模型,最新的Isaac GR00T N1.6堪称“机器人界的GPT-4o”,其最核心的创新是双系统架构设计,完美复刻了人类“本能反应+深度思考”

By Ne0inhk
探索Maas平台与阿里 QWQ 技术:AI调参的魔法世界

探索Maas平台与阿里 QWQ 技术:AI调参的魔法世界

摘要:本文介绍了蓝耘 Maas 平台在人工智能领域的表现及其核心优势,包括强大的模型支持、高效的资源调度和友好的操作界面。文章还探讨了蓝耘 Maas 平台与阿里 QWQ 技术的融合亮点及应用拓展实例,并提供了调参实战指南,最后对蓝耘 Maas 平台的未来发展进行了展望。 1.蓝耘 Maas 平台初印象 以下是关于“Maas”和“阿里 QWQ”的概念解释: 1.1 MaaS概念 * 定义:MaaS(Model as a Service),即“模型即服务”,是一种将机器学习模型部署到企业端,以API、SaaS或开源软件的形式提供给用户使用的服务模式。通过MaaS,用户能够简单调用模型来获得所需服务,无需了解模型内部的复杂算法和实现细节。 * 优势:MaaS降低了模型部署和应用的门槛,使开发人员和业务人员可以更专注于模型的优化和创新。它帮助企业实现高效智能的数据分析和决策,提高开发效率和模型应用的灵活性。 * 应用:MaaS平台会提供经过训练和优化后的模型,用户可以根据需求通过API等方式调用这些模型,

By Ne0inhk
让AI帮你炒币?这个开源项目把“躺赚梦“照进了现实

让AI帮你炒币?这个开源项目把“躺赚梦“照进了现实

写在前面:一个普通人的量化交易觉醒 你是否曾经在凌晨三点盯着K线图,眼睛酸涩却不敢睡,生怕错过那个"完美"的入场时机?你是否曾经因为工作错过了一波行情,然后看着币价暴涨懊悔不已?我猜你一定也想过:要是有个机器人帮我24小时盯盘该多好? 别说,这事儿还真有人做了。而且不是那种"交个年费999就能躺赚百万"的骗局,而是一个真正开源、可验证、能实战的AI量化交易系统。 它叫NOFX——一个让AI模型真正"上岗"交易的智能系统。更有趣的是,它还能让不同的AI模型互相PK,就像斗地主一样,看看是DeepSeek的决策更稳健,还是Qwen的操作更激进。 今天我们就来聊聊这个项目到底怎么玩,以及普通人该如何把它跑起来。 第一章:这个系统到底是个什么东西? 1.1 一句话概括 NOFX是一个AI驱动的加密货币自动交易操作系统。它让AI模型(比如DeepSeek、Qwen)直接分析市场数据、做出交易决策、执行买卖操作——全程无需人工干预。 你可能会问:

By Ne0inhk
上个视频爆了!2026年AI“白嫖”终极指南:这6个渠道,帮你省下几万块算力费(附OpenClaw独家配置)

上个视频爆了!2026年AI“白嫖”终极指南:这6个渠道,帮你省下几万块算力费(附OpenClaw独家配置)

兄弟们,上期发的那个“2026 年免费生产级 AI 大集合”的视频,没想到直接爆了! 看来大家和我的痛点都是一样的:官方的 AI 实在太贵了! ChatGPT、Claude 动不动就是 20 美金/月,好用是好用,但限制也多: * 动不动封号; * 5 小时 50 条的限制卡得死死的; * 用起来并没有想象中那么爽。 既然大家想看更详细的,今天大古就把压箱底的存货都掏出来。 这篇长文,详细教大家如何在 2026 年,用上这些免费/白菜价的顶级算力,搭建属于你的生产级工作流。 1. 新手首选:国产良心 Trae 💰 费用:0 元(个人免费) ⭐ 推荐指数:⭐⭐⭐⭐⭐ 如果你是刚接触 AI 编程的新手,连代码都没怎么碰过,Trae 绝对是你的第一步首选。

By Ne0inhk