小知识,大挑战!本文正在参与“程序员必备小知识”创作活动链表的中间节点
给定一个头结点为 **head** 的非空单链表,返回链表的中间结点。
如果有两个中间结点,则返回第二个中间结点。
输入:[1,2,3,4,5,6]
输出:此列表中的结点 4
由于该列表有两个中间结点,值分别为 3 和 4,我们返回第二个结点。
示例节点
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
因为是这种节点形式,我们不能直接的去调用方法,需要我们自己进行编写
首先,我们用最简单的做法去做一下这道题,我们直接将链表转化成数组,取中间值输出即可
public ListNode middleNode(ListNode head) {
ListNode [] A=new ListNode[100];
int a=0;
while (head!=null){
A[a++]=head;
head=head.next;
}
return A[a/2];
}
优化1
当我们利用数组做完这道题的时候,我们再仔细地去想一想我们可以省略数组,我们进行两边遍历,第一次统计元素个数N,第二次遍历到N/2是时我们输出即可。
public ListNode middleNode(ListNode head) {
int n = 0;
ListNode list = head;
while (list != null) {
n++;
list = list.next;
}
int k = 0;
list = head;
while (k < n / 2) {
k++;
list = list.next;
}
return list;
}
优化2
但这一次优化我们进行了两遍遍历,我们找链表的点是一个比较特殊的一个点,在二分之一处,使用双指针中的快慢指针,一前一后,当快指针到达链表尾部时,满指针一定在链表中间位置
public ListNode middleNode(ListNode head) {
ListNode slow = head, fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
删除链表倒数第n个节点
示例节点
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
因为经过上面那道题之后,思路十分明确就是先进行一遍遍历之后确定链表长度,之后在进行一遍遍历之后,删除节点,所以这道问题很简单的就解决了
//删除节点函数
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode d=new ListNode(0,head);
int lenght=get(head);
ListNode c=d;
for (int i=1;i<lenght-n+1;i++){
c=c.next;
}
c.next=c.next.next;
return d.next;
}
//获取链表长度函数
public int get(ListNode head){
int lenght=0;
while (head!=null){
lenght++;
head=head.next;
}
return lenght;
}
优化
相较于前一道题,前一道是找到中间位置,本题是指定位置,我们还是可以利用双指针,只不过之前属于定比,此题属于定差,我们只需要保证指针的距离为n,当前指针到达链表尾部是,后指针就处于n的位置
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(0, head);
ListNode first = head;
ListNode second = dummy;
for (int i = 0; i < n; ++i) {
first = first.next;
}
while (first != null) {
first = first.next;
second = second.next;
}
second.next = second.next.next;
ListNode ans = dummy.next;
return ans;
}