leetcode地址: leetcode.cn/problems/re…
原题描述:
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
进阶:一次循环完成
解题思路:
方法1:
多次循环法,第一次循环知道链表的长度,根据链表长度第二次循环就能找到链表的位置,再进行相应操作。 这个太简单了不做实现,我也没这么做。
方法2:
额外数据结构法,第一次循环将链表放入ArrayList结构,这样就能规避掉第二次循环找到这个节点的操作,而是通过arraylist取下标来获取,然后注意处理好边界条件即可。
代码如下:
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ArrayList<ListNode> list = new ArrayList<>();
ListNode temp = head;
while(temp!=null){
list.add(temp);
temp = temp.next;
}
int size = list.size();//size=6 n=2 index=4 实际第五 倒数第二
int index = size - n;
ListNode node = list.get(index);
ListNode next = node.next;
if(index-1>=0){
ListNode pre = list.get(index-1);
pre.next = next;
}else{
head = next;
}
return head;
}
}
方法3:
快慢指针,定义一个快指针一个慢指针,快指针先走n,然后快慢一起走,这样快走到null的时候,慢走到需要删除的节点。省略了o(n)的空间消耗。不过这样处理指针转换会麻烦一点,具体请看以下代码:
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode index1 = head;
ListNode index2 = head;
ListNode pre = head;
for(int i = 0;i<n;i++){
index1 = index1.next;
}
for(int i = 0;index1!=null;i++){
index1 = index1.next;
index2 = index2.next;
if(i!=0){
pre = pre.next;
}
}
ListNode node = index2;
ListNode next = node.next;
if(pre!=node){
pre.next = next;
}else{
head = next;
}
return head;
}
}
请大家着重理解最后的if判断,为什么是pre!=node,而不是pre!=head;