Flask接口签名sign原理与实例代码浅析
374
2022-10-22
教你如何轻松学会Java快慢指针法
一、什么是快慢指针?
快慢指针就是定义两根指针,移动的速度一快一慢,以此来制造出自己想要的差值。这个差值可以让我们找到链表上相应的节点。
那快慢指针可以解决哪些实际问题呢,接下来我们一起看看吧!
二、使用快慢指针来找到链表的中点
1.首先我们设置两个指针slow和fast,这2个指针的初始位置相同,都指向链表的头结点,然后slow指针每次移动一步,fast指针每次移动两步;
2.如果链表中节点个数为偶数时,当快指针无法继续移动时,慢指针刚好指向中点;如果链表中节点个数为奇数时,当快指针走完,慢指针指向中点的前一个节点。
public ListNode reverseStore(ListNode head) {
// 初始化,让快指针和慢指针都处于链表的头部
ListNode slow=head;
ListNode fast=head;
while(fast!=null&&fast.next!=null){//如果快指针并且下一个不为空
fast=fast.next.next;//快指针移动两个
slow=slow.next;//慢指针移动一个
}
return slow;
}
三、利用快慢指针来判断链表中是否有环
问题描述: 给定一个链表,判断链表中是否有环。
以下两种情况都属于链表中存在环,“0”字型和“6”字型
这个时候我们的解决方案就是利用“快慢指针”, 慢指针针每次走一步,快指针每次走两步,如果相遇就说明有环,如果有一个为空说明没有环。代码比较简单 (在代码下面会专门讲解思路的,放心!)
public boolean hasCycle(ListNode head) {
if (head == null)
return false;
//快慢两个指针,初始时都指向链表的头结点
ListNode slow = head;
ListNode fast = head;
while (fast != null && fast.next != null) {
//慢指针每次走一步
slow = slow.next;
//快指针每次走两步
fast = fast.next.next;
//如果相遇,说明有环,直接返回true
if (slow == fast)
return true;
}
//否则就是没环
return false;
}
到这里大家可能就有疑问了,为什么快慢指针就一定能判断是否有环。我们可以这样来思考一下,假如有环,那么快慢指针最终都会走到环上,假如环的长度是m,快慢指针最近的间距是n,如下图中所示
下面说的两点相距是指 “快指针还需要多远可以再次追到慢指针”
快指针每次走两步,慢指针每次走一步,所以每走一次快慢指针的间距就要缩小一步,在图一中当走n次的时候就会相遇,在图二中当走m-n次的时候就会相遇。这样就解释清楚了读者的疑问了。
四、删除链表的倒数第n个节点
问题描述:删除倒数第n个节点,那就等于是要我们先找出待删除元素前一个元素,也就是第n-1个节点。聪明的你肯定发现了,我们又把这个问题转化为找链表上的某个节点的问题了,这是快慢指针最擅长的场景。
思路很简单,我们一开始就让fast指针比slow指针快n+1个元素,接下来,两个指针都是一步一步来往下走。那么当fast指针走完时,slow指针就刚刚好停留在第(n-1)个元素上。
//删除链表倒数第n个节点
public ListNode removeBackEndNode(ListNode head, int n) {
if (head == null || head.next == null) {
return null;
}
ListNode dummyHead = new ListNode(-1);
dummyHead.next = head;
//初始时让快慢指针都指向链表的头部
ListNode slow = dummyHead;
ListNode fast = dummyHead;
for (int i = 0; i < n + 1; i++) {
fast = fast.next;
}
while (fast != null) {
slow = slow.next;
fast = fast.next;
}
slow.next = slow.next.next; //为了解决断链问题
return dummyHead.next;
}
五、判断是否是回文链表
快指针每次前进两个单位,慢指针每次前进一个单位并修改其next节点指向前一个节点,所以当快指针到达链表末尾的时候(空节点或空节点的前一个节点),慢指针刚好在中间,如下图所示
此时慢指针继续向后走,同时开辟一个新节点往前走,看下图
判断链表中点前后是否相同,达到判断回文串的目的,如下图所示
代码如下:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public boolean isPalindrome(ListNode head) {
if(head == null || head.next == null){
return true;
}
ListNode pre = null;//指向前一个节点的指针
ListNode slow = head;//慢指针
ListNode fast = head;//快指针
while(fast!=null&&fast.next!=null){
fast = fast.next.next;
ListNode next = slow.next;
slow.next = pre;//修改慢指针走过的节点指向前一个节点
pre = slow;
slow = next;
}
if(fast != null){
slow = slow.next;
//当长度为奇数是,慢指针需要再走一个单位
http:// }
while(pre!=null) {
//判断是否为回文串
if(pre.val!=slow.val){
return false;
}
pre = pre.next;
slow = slow.next;
}
return true;
}
}
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~