【tricks】找到列表的中点【快慢指针】


     * 总结:
     * 
     *  开始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 : "无");

	}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值