* 总结:
*
* 开始slow 和 fast的位置: 0 1 2 3 4 | 节点数 1 2 3 4 5*-----------------------------------------------------------------------------------------------------------------
* 中点(《): 1S 2F | 中点位置 1 1 2 2 3| (前置判断,1-2内的直接返回头节点)
| if (head == null || head.next == null || head.next.next == null) return head;
*-----------------------------------------------------------------------------------------------------------------
* 中点(》): 1S1F | 1 2 2 3 3| (前置判断,1内的直接返回头结点)
| if (head == null || head.next == null) return head;
*-----------------------------------------------------------------------------------------------------------------
* 中点(《)前一个点: 0S 2F | N=没有 N N 1 1 2| (前置判断,1-2内的直接返回头结点,头结点可空)
| if (head == null || head.next == null || head.next.next == null) return head;
*-----------------------------------------------------------------------------------------------------------------
* 中点(》)前一个点: 0S 1F | N 1 1 2 2| (前置判断,1内的直接返回空)
| if (head == null || head.next == null) return null;
| (前置判断,2个直接返回头结点)
| if (head.next.next == null) return head;
*-----------------------------------------------------------------------------------------------------------------
* S从1开始是找中点本身;S从0开始是找中点前一个点
* F从2开始是找中点(偶数个是中上点),F从1开始是找中点(偶数个是中下点)
package com.leetcode.tricks;
import java.util.ArrayList;
/*
* 使用快慢指针找到列表的中点
*/
public class ListNodePivotWithFastSlow {
//--------------------------------------Node节点--------------------------------
public static class Node {
public int value;
public Node next;
public Node(int v) {
value = v;
}
}
//--------------------------------------求中点及中点前一个点--------------------------------
/**
* @description: 返回列表的中上 pivot <|
* @param head
* @return
*/
public static Node midOrUpMidNode(Node head) {
// 有两个以内的,
if (head == null || head.next == null || head.next.next == null) {
return head;
}
// 链表有3个点或以上
Node slow = head.next;
Node fast = head.next.next;
while (fast.next != null && fast.next.next != null) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
/**
* @description: 返回列表的中下 pivot |>
* @param head
* @return
*/
public static Node midOrDownMidNode(Node head) {
// 有一个以内的,
if (head == null || head.next == null) {
return head;
}
// 两个以上
Node slow = head.next;
Node fast = head.next;
while (fast.next != null && fast.next.next != null) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
/**
* @description: 返回列表的中间点的前一个点 pivot <<|
* @param head
* @return
*/
public static Node midOrUpMidPreNode(Node head) {
// 有两个以内的,
if (head == null || head.next == null || head.next.next == null) {
return null;
}
// 链表有3个点或以上
Node slow = head;
Node fast = head.next.next;
while (fast.next != null && fast.next.next != null) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
/**
* @description: 返回列表的中下下 pivot |>>
* @param head
* @return
*/
public static Node midOrDownMidPreNode(Node head) {
// 只有一个点
if (head == null || head.next == null) {
return null;
}
// 只有两个点
if (head.next.next == null) {
return head;
}
// 三点及以上
Node slow = head;
Node fast = head.next;
while (fast.next != null && fast.next.next != null) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
/*
* 总结:
* list:(奇数)中点为 4 从0开始
* 0 1 2 3 4 5 6 7 8
* 中点 |
* 中点前一个点 |
* -------------------------------------------------------------
* list:(偶数) 中点为 从0
* 0 1 2 3 4 5 6 7
* 中点(《): |
* 中点(》): |
* 中点(《)前一个点: |
* 中点(》)前一个点:
* ------------------------------------------------------------
* 开始slow 和 fast的位置: 0 1 2 3 4 | 节点数 1 2 3 4 5
* 中点(《): S F | 中点位置 1 1 2 2 3
* 中点(》): SF | 1 2 2 3 3
* 中点(《)前一个点: S F | N=没有 N N 1 1 2
* 中点(》)前一个点: S F | N 1 1 2 2
* -------------------------------------------------------------
* S从1开始是找中点本身;S从0开始是找中点前一个点
* F从2开始是找中点(偶数个是中上点),F从1开始是找中点(偶数个是中下点)
*/
//----------------------------------------对比---------------------------------------
/*
* 以下是把Node遍历放入ArrayList后,
* 有ArrayList的size()来求中点的。
*
*/
public static Node right1(Node head) {
if (head == null) {
return null;
}
Node cur = head;
ArrayList<Node> arr = new ArrayList<>();
while (cur != null) {
arr.add(cur);
cur = cur.next;
}
return arr.get((arr.size() - 1) / 2);
}
public static Node right2(Node head) {
if (head == null) {
return null;
}
Node cur = head;
ArrayList<Node> arr = new ArrayList<>();
while (cur != null) {
arr.add(cur);
cur = cur.next;
}
return arr.get(arr.size() / 2);
}
public static Node right3(Node head) {
if (head == null || head.next == null || head.next.next == null) {
return null;
}
Node cur = head;
ArrayList<Node> arr = new ArrayList<>();
while (cur != null) {
arr.add(cur);
cur = cur.next;
}
return arr.get((arr.size() - 3) / 2);
}
public static Node right4(Node head) {
if (head == null || head.next == null) {
return null;
}
Node cur = head;
ArrayList<Node> arr = new ArrayList<>();
while (cur != null) {
arr.add(cur);
cur = cur.next;
}
return arr.get((arr.size() - 2) / 2);
}
//----------------------------------main----------------------------------------------
public static void main(String[] args) {
Node test = null;
test = new Node(0);
test.next = new Node(1);
test.next.next = new Node(2);
test.next.next.next = new Node(3);
test.next.next.next.next = new Node(4);
test.next.next.next.next.next = new Node(5);
test.next.next.next.next.next.next = new Node(6);
test.next.next.next.next.next.next.next = new Node(7);
test.next.next.next.next.next.next.next.next = new Node(8);
// 一个是快慢指针,一个是List的size
Node ans1 = null;
Node ans2 = null;
// 中点
ans1 = midOrUpMidNode(test);
ans2 = right1(test);
System.out.println(ans1 != null ? ans1.value : "无");
System.out.println(ans2 != null ? ans2.value : "无");
ans1 = midOrDownMidNode(test);
ans2 = right2(test);
System.out.println(ans1 != null ? ans1.value : "无");
System.out.println(ans2 != null ? ans2.value : "无");
// 中点前一个点
ans1 = midOrUpMidPreNode(test);
ans2 = right3(test);
System.out.println(ans1 != null ? ans1.value : "无");
System.out.println(ans2 != null ? ans2.value : "无");
ans1 = midOrDownMidPreNode(test);
ans2 = right4(test);
System.out.println(ans1 != null ? ans1.value : "无");
System.out.println(ans2 != null ? ans2.value : "无");
}
}