首先我们的链表题目 都是分为两种,一种是使用容器,但是另外一种就是不使用容器的.
那么我们接下来的这些问题的都会根据这两种策略进行分析.
问题一:输入链表头节点,奇数长度返回中点,偶数长度返回上中点.
首先如果我们先进行分析使用容器的策略
首先我们先分析
如果我们将各个节点都放进数组中,那么我们的中点问题可以根据数组的下标进行解决.
1->2->3->4->5
节点3 的下标就是2,那么我们符合我们这个下标的计算公式就是-->(N/2)或者((N-1)/2)
这个只是奇数的求解方式.
但是我们的还是要就如果是偶数个数节点那么就取上节点
1->2->3->4->5->6
如果要求上节点那么就只能取到 ->(N-1)/2
所以:
public static Node midOrUpNode(Node head){
if(head==null ||head.next==null){
return head;
}
ArrayList<Node> list = new ArrayList<>();
while(head!=null){
list.add(head);
head = head.next;
}
int N = list.size();
return list.get((N-1)>>1);
}
同时我们不使用容器的策略就是使用快慢指针.
public static Node midOrUpMidNode(Node head){
if (head == null || head.next == null || head.next.next == null) {
return head;
}
// 链表有3个点或以上
Node slow = head;
Node fast = head;
while (fast.next != null && fast.next.next != null) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
问题二:输入链表头结点,奇数长度返回中点,偶数长度返回下中点.
容器解法:
public static Node midOrDownNode(Node head){
if(head==null || head.next==null){
return head;
}
ArrayList<Node> list = new ArrayList<>();
while(head!=null){
list.add(head);
head = head.next;
}
int N = list.size();
return list.get(N>>1);
}
快慢指针解法:
public static Node middleOrDown(Node head){
if(head==null || head.next==null){
return head;
}
if(head.next.next==null){
return head.next;
}
Node fast = head.next;
Node slow = head.next;
while(fast.next!=null && fast.next.next!=null){
fast = fast.next.next;
slow = slow.next;
}
return slow;
}
问题二:输入链表头结点,奇数长度返回中点的前一个,偶数长度返回上节点的前一个
容器解法:
public static Node midOrUpMidprevNode(Node head){
if(head==null || head.next==null){
return head;
}
ArrayList<Node> list = new ArrayList<>();
while(head!=null){
list.add(head);
head = head.next;
}
int N = list.size();
return list.get((N-3)>>1);
}
快慢指针:
public static Node midOrUpPrevNode(Node head){
if(head==null || head.next==null || head.next.next==null){
return null;
}
Node fast = head.next.next;
Node slow = head;
while(fast.next!=null && fast.next.next!=null){
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
问题四:输入链表头结点,奇数长度返回中点的前一个,偶数长度返回下中点的前一个
容器:
public static Node midOrMidprevNode(Node head){
if(head==null || head.next==null || head.next.next==null){
return head;
}
ArrayList<Node> list = new ArrayList<>();
while(head!=null){
list.add(head);
head = head.next;
}
int N = list.size();
return list.get((N-2)>>1);
}
快慢指针:
public static Node midOrDownMidprev(Node head){
if(head==null || head.next==null){
return null;
}
if(head.next.next==null){
return head;
}
Node fast = head.next;
Node slow = head;
while(fast.next!=null && fast.next.next!=null){
fast = fast.next.next;
slow = slow.next;
}
return slow;
}
总结:链表中点问题的边界条件不可以硬背,什么时候用,什么时候推.