快慢指针的应用

1.判断单链表是否存在环

 1 * Definition for singly-linked list.
 2  * public class ListNode {
 3  *     public int val;
 4  *     public ListNode next;
 5  *     public ListNode(int x) {
 6  *         val = x;
 7  *         next = null;
 8  *     }
 9  * }
10  */
11 public class Solution {
12     public bool HasCycle(ListNode head) {
13          if(head == null){
14             return false;
15         }
16         ListNode slow = head;
17         ListNode fast = head;
18         while (fast !=null && fast.next!=null){
19             slow = slow.next;
20             fast = fast.next.next;
21             if(slow == fast){
22                 return true;
23             }
24         }
25         return false;
26     }
27 }

如果链表存在环,就好像操场的跑道是一个环形一样。此时让快慢指针都从链表头开始遍历,快指针每次向前移动两个位置,慢指针每次向前移动一个位置;如果快指针到达NULL,说明链表以NULL为结尾,没有环。如果快指针追上慢指针,则表示有环.

2.判断两个单链表是否相交,如果相交,找到他们的第一个公共节点

编写一个程序,找到两个单链表相交的起始节点。

如下面的两个链表:

在节点 c1 开始相交。

示例 1:

输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
输出:Reference of the node with value = 8
输入解释:相交节点的值为 8 (注意,如果两个列表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。

示例 2:

输入:intersectVal = 2, listA = [0,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
输出:Reference of the node with value = 2
输入解释:相交节点的值为 2 (注意,如果两个列表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [0,9,1,2,4],链表 B 为 [3,2,4]。在 A 中,相交节点前有 3 个节点;在 B 中,相交节点前有 1 个节点。

示例 3:

输入:intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
输出:null
输入解释:从各自的表头开始算起,链表 A 为 [2,6,4],链表 B 为 [1,5]。由于这两个链表不相交,所以 intersectVal 必须为 0,而 skipA 和 skipB 可以是任意值。
解释:这两个链表不相交,因此返回 null。

这道题有三种解决方法(1)利用快慢指针将链表1的尾结点的next赋给链表2的头结点,在循环过程中如果slow==fast则证明存在环,之后再创建一组快慢指针找到相的结点
 1 /**
 2  * Definition for singly-linked list.
 3  * public class ListNode {
 4  *     public int val;
 5  *     public ListNode next;
 6  *     public ListNode(int x) { val = x; }
 7  * }
 8  */
 9 public class Solution {
10     public ListNode GetIntersectionNode(ListNode headA, ListNode headB) {
11         if(headA==null||headB==null)
12             return null;
13         ListNode tmp=headB;
14         while(tmp.next!=null)
15         {
16             tmp=tmp.next;
17         }
18         tmp.next=headB;
19         ListNode slow=headA;
20         ListNode fast=headA;
21         while(fast!=null&&fast.next!=null)
22         {
23             slow=slow.next;
24             fast=fast.next.next;
25             if(fast==slow)
26             {
27                 slow=headA;
28                 while(slow!=fast)
29                 {
30                     slow=slow.next;
31                     fast=fast.next;
32                 }
33                 tmp.next=null;
34                 return fast;
35             }
36         }
37         tmp.next=null;
38         return null;
39     }
40 }
(2)两链表相连

 1 /**
 2  * Definition for singly-linked list.
 3  * public class ListNode {
 4  *     public int val;
 5  *     public ListNode next;
 6  *     public ListNode(int x) { val = x; }
 7  * }
 8  */
 9 public class Solution {
10     public ListNode GetIntersectionNode(ListNode headA, ListNode headB) {
11         if(headA == null || headB == null) return null;
12         ListNode pA = headA, pB = headB;
13         // 在这里第一轮体现在pA和pB第一次到达尾部会移向另一链表的表头, 而第二轮体现在如果pA或pB相交就返回交点, 不相交最后就是null==null
14         while(pA != pB) {
15             pA = pA == null ? headB : pA.next;
16             pB = pB == null ? headA : pB.next;
17         }
18         return pA;
19     }
20 }

 (3)使两个链表长度相等,循环依次比较

3.用快慢指针获取中间结点

 1 /**
 2  * Definition for singly-linked list.
 3  * public class ListNode {
 4  *     public int val;
 5  *     public ListNode next;
 6  *     public ListNode(int x) { val = x; }
 7  * }
 8  */
 9 public class Solution {
10     public ListNode MiddleNode(ListNode head) {
11         ListNode slow=head;
12         ListNode fast=head;
13         if(head!=null)
14         {
15         while(fast!=null&&fast.next!=null)
16             {
17                 slow=slow.next;
18                 fast=fast.next.next;
19             }
20         }
21
22         return slow;
23     }
24 }


通过找到中间结点的方法,也可以借此判断该链表是否是回文

 

 1 /**
 2  * Definition for singly-linked list.
 3  * public class ListNode {
 4  *     public int val;
 5  *     public ListNode next;
 6  *     public ListNode(int x) { val = x; }
 7  * }
 8  */
 9 public class Solution {
10     public bool IsPalindrome(ListNode head) {
11         ListNode slow = head;
12             ListNode fast = head;
13             ListNode temp = head;
14             while(fast!=null&&fast.next!=null)
15             {
16                 slow = slow.next;
17                 fast = fast.next.next;
18             }
19             slow = ReverseList(slow);
20             while(slow!=null)
21             {
22                 if (temp.val != slow.val)
23                     return false;
24                 else
25                 {
26                     temp = temp.next;
27                     slow = slow.next;
28                 }
29             }
30             return true;
31     }
32     public ListNode ReverseList(ListNode head) {
33         ListNode prev = null;
34         ListNode curr = head;
35         while (curr != null) {
36             ListNode nextTemp = curr.next;
37             curr.next = prev;
38             prev = curr;
39             curr = nextTemp;
40         }
41         return prev;
42     }
43 }





原文地址:https://www.cnblogs.com/gsh520/p/10926118.html

时间: 2024-10-02 05:32:47

快慢指针的应用的相关文章

快慢指针原理--快速找到未知长度单链表的中间节点

package com.java.dataStruct; //节点类 public class Node<E> { E item; Node next; public Node(){ } public Node(E element){ this.item = element; } public Node(E element, Node next){ this.item = element; this.next = next; } } Node p1,r1; Node L1 = new Node

快慢指针

//最快的方式查找一个链表中的最中间节点#include<stdio.h> #define SIZE 100000 typedef struct Node{ int data; struct Node* next; struct Node* prev; }Node; Node f[SIZE]; int index = 0; Node* head; Node* getnode(){ return &f[index++]; } void init(){ index = 0; head =

求单链表的中间节点,用快慢指针

? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 Node* findMid(Node* &head) {     if(head == NULL||head->next == NULL)         return head;          Node* p = head;     Node* q = head;     while(q->next->next&&(q = q->next))     {         p = p-

reorder-list——链表、快慢指针、逆转链表、链表合并

Given a singly linked list L: L0→L1→-→Ln-1→Ln,reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→- You must do this in-place without altering the nodes' values. For example,Given{1,2,3,4}, reorder it to{1,4,2,3}. 由于链表尾端不干净,导致fast->next!=NULL&&fast->next-&

快慢指针到底指向哪?

快慢指针到底指向哪?这个问题对于刚接触这种技巧的人来说往往把握不好.下面将以单链表为例, 说一点我个人的理解. 1) 比较通用的写法 if (head == NULL || head->next == NULL) return true; ListNode *fast = head, *slow = head, *prev = NULL; while (fast && fast->next) { prev = slow; slow = slow->next; fast =

[LeetCode] Remove Nth Node From End of List 快慢指针

Given a linked list, remove the nth node from the end of list and return its head. For example, Given linked list: 1->2->3->4->5, and n = 2. After removing the second node from the end, the linked list becomes 1->2->3->5. Note:Given n

Minimum Window Substring &amp;&amp;&amp; Longest Substring Without Repeating Characters 快慢指针,都不会退,用hashmap或者其他结构保证

1 public class Solution { 2 public static int lengthOfLongestSubstring(String s) { 3 4 char[] arr = s.toCharArray(); 5 int pre = 0; 6 7 HashMap<Character, Integer> map = new HashMap<Character, Integer>(); 8 9 for (int i = 0; i < arr.length;

【Leetcode解题报告】快慢指针

快慢指针中的快慢指的是移动的步长,即每次向前移动速度的快慢.例如可以让快指针每次沿链表向前移动2,慢指针每次向前移动1次. Leetcode 141 Linked List Cycle 问题描述 Given a linked list, determine if it has a cycle in it. Follow up: Can you solve it without using extra space? 分析与解法 大家可以想一下上体育课长跑的情景.当同学们绕着操场跑步的时候,速度快的

快慢指针,怎样快速获取链表的中间元素

有一个链表,怎样快速获取中间节点的元素. 方法1 遍历一下链表,确认长度,获取中间的节点元素,时间复杂度O(N) 方法2 设置两个指针,一个遍历p->nexr  一个 p->next->next,快慢指针的思想  时间复杂度为O(n/2) 代码: 1 //腾讯面试题,获取一个单链表的中间位置 2 Status GetMidNode(LinkList L,ElemType *e) 3 { 4 LinklList search,mid; 5 mid =search=L; 6 while (s

快慢指针及应用【转】

快慢指针中的快慢指的是移动的步长,即每次向前移动速度的快慢.例如可以让快指针每次沿链表向前移动2,慢指针每次向前移动1次. 判断单链表是否为循环链表 让快慢指针从链表头开始遍历,快指针向前移动两个位置,慢指针向前移动一个位置;如果快指针到达NULL,说明链表以NULL为结尾,不是循环链表.如果 快指针追上慢指针,则表示出现了循环. fast=slow=head; fast=fast->next->next; slow=slow->next; while(true){ if (fast==