Java双指针法怎么使用(java,开发技术)

时间:2024-04-28 19:26:15 作者 : 石家庄SEO 分类 : 开发技术
  • TAG :

前言

通常用在线性的数据结构中,比如链表和数组。

指针其实就是数据的索引或者链表的结点。两个指针朝着左右两个方向移动,直到满足搜索条件。 双指针可分为同向双指针、异向双指针、快慢指针、滑动窗口。根据需求选择双指针的模型,比如 删除数组或链表中重复的元素,同向双指针(线性表前提是有序的); 快慢指针一般用在链表中,比如求链表的中点、判断链表是否有环、判断链表换的起点、环的长度、以及链表的倒数第K个元素; 比如在二分查找中用的就是异向双指针; 滑动窗口其实就是在数组或者链表某个区间上的操作,比如求最长/最短子字符串或是特定子字符串的长度要求。

1.判断链表是否有环

力扣141题

给你一个链表的头节点 head ,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。

如果链表中存在环 ,则返回 true 。 否则,返回 false 。

Java双指针法怎么使用

代码实现

publicclassSolution{//快慢指针法publicbooleanhasCycle(ListNodehead){ListNodefast=head;ListNodelow=head;while(fast!=null&&fast.next!=null){fast=fast.next.next;low=low.next;//此时相遇了if(fast==low){returntrue;}}returnfalse;}}

2.查找链表中间的元素

力扣876题

给定一个头结点为 head 的非空单链表,返回链表的中间结点。

如果有两个中间结点,则返回第二个中间结点。

Java双指针法怎么使用

代码实现

//快慢指针法publicListNodemiddleNode(ListNodehead){ListNodelow=head,fast=head;while(fast!=null&&fast.next!=null){//慢指针走一步low=low.next;//快指针走两步fast=fast.next.next;}//奇数,fast.next=null时,low即为所求//偶数,fsat==null时,low即为所求returnlow;}

3.奇偶排序前奇后偶

力扣328题

给定单链表的头节点 head ,将所有索引为奇数的节点和索引为偶数的节点分别组合在一起,然后返回重新排序的列表。

第一个节点的索引被认为是 奇数 , 第二个节点的索引为 偶数 ,以此类推。

Java双指针法怎么使用

代码实现

publicListNodeoddEvenList(ListNodehead){if(head==null){returnhead;}ListNodefastHead=head.next;ListNodelowTail=head;//奇数链表ListNodefastTail=fastHead;//偶数链表while(fastTail!=null&&fastTail.next!=null){//更新奇数节点时,奇数节点的后一个节点需要指向偶数节点的后一个节点lowTail.next=fastTail.next;lowTail=lowTail.next;//更新偶数节点时,偶数节点的后一个节点需要指向奇数节点的后一个节点fastTail.next=lowTail.next;fastTail=fastTail.next;}//合并两个链表lowTail.next=fastHead;returnhead;}

4.删除排序链表的重复元素

力扣82题

给定一个已排序的链表的头 head , 删除原始链表中所有重复数字的节点,只留下不同的数字 。返回 已排序的链表

Java双指针法怎么使用

代码实现

publicListNodedeleteDuplicates(ListNodehead){//虚拟头节点法ListNodedummyHead=newListNode(-1);dummyHead.next=head;ListNodeprev=dummyHead;ListNodecur=prev.next;while(cur!=null){//引入next指针ListNodenext=cur.next;if(next==null){//只有一个元素returndummyHead.next;}if(cur.val!=next.val){//cur不是重复节点,三指针都移动cur=cur.next;prev=prev.next;}else{//让next指针一直向后移动,直到与cur.val不相等的节点位置while(next!=null&&cur.val==next.val){next=next.next;}//此时next指向了第一个不重复的元素//此时prev-next之间所有重复元素全部删除prev.next=next;cur=next;}}returndummyHead.next;}

5.三数之和

力扣15题

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

Java双指针法怎么使用

代码实现

publicList<List<Integer>>threeSum(int[]nums){intn=nums.length;Arrays.sort(nums);List<List<Integer>>ans=newArrayList<List<Integer>>();//枚举afor(intfirst=0;first<n;++first){//需要和上一次枚举的数不相同if(first>0&&nums[first]==nums[first-1]){continue;}//c对应的指针初始指向数组的最右端intthird=n-1;inttarget=-nums[first];//枚举bfor(intsecond=first+1;second<n;++second){//需要和上一次枚举的数不相同if(second>first+1&&nums[second]==nums[second-1]){continue;}//需要保证b的指针在c的指针的左侧while(second<third&&nums[second]+nums[third]>target){--third;}//如果指针重合,随着b后续的增加//就不会有满足a+b+c=0并且b<c的c了,可以退出循环if(second==third){break;}if(nums[second]+nums[third]==target){List<Integer>list=newArrayList<Integer>();list.add(nums[first]);list.add(nums[second]);list.add(nums[third]);ans.add(list);}}}returnans;}

6.分割链表

力扣面试题02.04

给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。

你不需要 保留 每个分区中各节点的初始相对位置。

Java双指针法怎么使用

代码实现

publicListNodepartition(ListNodehead,intx){//创建small和big两个小链表的头节点ListNodesmallHead=newListNode(-1);ListNodebigHead=newListNode(-1);//按照升序插入,因此需要尾插//分别指向两个子链表的尾部ListNodesmallTail=smallHead;ListNodebigTail=bigHead;//遍历原链表,根据值放入small和big链表中while(head!=null){if(head.val<x){smallTail.next=head;smallTail=head;}else{bigTail.next=head;bigTail=head;}head=head.next;}bigTail.next=null;//拼接小链表和大链表smallTail.next=bigHead.next;returnsmallHead.next;}

7.合并两个有序的数组

力扣88题

给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。

注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。

Java双指针法怎么使用

代码实现

publicvoidmerge(int[]nums1,intm,int[]nums2,intn){intp1=0,p2=0;int[]sorted=newint[m+n];intcur;while(p1<m||p2<n){if(p1==m){cur=nums2[p2++];}elseif(p2==n){cur=nums1[p1++];}elseif(nums1[p1]<nums2[p2]){cur=nums1[p1++];}else{cur=nums2[p2++];}sorted[p1+p2-1]=cur;}for(inti=0;i!=m+n;++i){nums1[i]=sorted[i];}}

8.两数之和&mdash;输入有序数组

力扣167题

给你一个下标从 1 开始的整数数组 numbers ,该数组已按 非递减顺序排列 ,请你从数组中找出满足相加之和等于目标数 target 的两个数。如果设这两个数分别是 numbers[index1] 和 numbers[index2] ,则 1 <= index1 < index2 <= numbers.length 。

以长度为 2 的整数数组 [index1, index2] 的形式返回这两个整数的下标 index1 和 index2。

Java双指针法怎么使用

代码实现

publicint[]twoSum(int[]numbers,inttarget){intlow=0,high=numbers.length-1;while(low<high){intsum=numbers[low]+numbers[high];if(sum==target){returnnewint[]{low+1,high+1};}elseif(sum<target){++low;}else{--high;}}returnnewint[]{-1,-1};}

9.长度最小的子数组

(力扣209)给定一个含有 n 个正整数的数组和一个正整数 target 。

找出该数组中满足其和 &ge; target 的长度最小的 连续子数组 [numsl, numsl+1, &hellip;, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0

Java双指针法怎么使用

代码实现

//滑动窗口法publicintminSubArrayLen(ints,int[]nums){intn=nums.length;if(n==0){return0;}intans=Integer.MAX_VALUE;intstart=0,end=0;intsum=0;while(end<n){sum+=nums[end];while(sum>=s){ans=Math.min(ans,end-start+1);sum-=nums[start];start++;}end++;}returnans==Integer.MAX_VALUE?0:ans;}

10.排序链表

给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。

Java双指针法怎么使用

解题思路

通过递归实现链表归并排序,有以下两个环节:

1,分割 cut 环节: 找到当前链表中点,并从中点将链表断开(以便在下次递归 cut 时,链表片段拥有正确边界); 我们使用 fast,slow 快慢双指针法,奇数个节点找到中点,偶数个节点找到中心左边的节点。 找到中点 slow 后,执行 slow.next = None 将链表切断。 递归分割时,输入当前链表左端点 head 和中心节点 slow 的下一个节点 tmp(因为链表是从 slow 切断的)。 cut 递归终止条件: 当head.next == None时,说明只有一个节点了,直接返回此节点。

2,合并 merge 环节: 将两个排序链表合并,转化为一个排序链表。 双指针法合并,建立辅助ListNode h 作为头部。 设置两指针 left, right 分别指向两链表头部,比较两指针处节点值大小,由小到大加入合并链表头部,指针交替前进,直至添加完两个链表。 返回辅助ListNode h 作为头部的下个节点 h.next。

代码实现

publicListNodesortList(ListNodehead){if(head==null||head.next==null)returnhead;ListNodefast=head.next,slow=head;while(fast!=null&&fast.next!=null){slow=slow.next;fast=fast.next.next;}ListNodetmp=slow.next;slow.next=null;ListNodeleft=sortList(head);ListNoderight=sortList(tmp);ListNodeh=newListNode(0);ListNoderes=h;while(left!=null&&right!=null){if(left.val<right.val){h.next=left;left=left.next;}else{h.next=right;right=right.next;}h=h.next;}h.next=left!=null?left:right;returnres.next;}
 </div> <div class="zixun-tj-product adv-bottom"></div> </div> </div> <div class="prve-next-news">
本文:Java双指针法怎么使用的详细内容,希望对您有所帮助,信息来源于网络。
上一篇:Java线程终止实例分析下一篇:

14 人围观 / 0 条评论 ↓快速评论↓

(必须)

(必须,保密)

阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18