翩若惊鸿,婉若游龙。荣曜秋菊,华茂春松。
文章首发于公众号 “蘑菇睡不着”,更多精彩内容欢迎关注
给你一个链表,删除链表的倒数第 n 个结点,而且返回链表的头结点。 node
示例 1:学习
输入:head = [1,2,3,4,5], n = 2 输出:[1,2,3,5]
示例 2:指针
输入:head = [1], n = 1 输出:[]
示例 3:code
输入:head = [1,2], n = 1 输出:[1]
提示:
链表中结点的数目为 sz
1 <= sz <= 30
0 <= Node.val <= 100
1 <= n <= szrem
这道题的包含两个问题:一是:怎么找到倒数第 N 个节点;二是:怎么删除一个节点。
先说怎么删除一个节点吧。其实也很简单,那就是要被删除节点的前置节点的next指针,指向被删除节点的下一个节点便可。代码片断为:node.next = node.next.next;其中 node 为 被删除节点的前置节点。
再说说怎么找到倒数第 N 个节点。这个就有讲头了,主要有两种方法:io
接下来会用两端代码来实现这两种方法。ast
方法一:class
class Solution { public ListNode removeNthFromEnd(ListNode head, int n) { if (head == null) { return head; } // 定义哑节点,主要是为了防止当 头节点也被删除的状况 ListNode listNode = new ListNode(0, head); // 快指针 ListNode fast = listNode; // 慢指针 ListNode slow = listNode; // 快指针先走 N 步 while(n > 0 && fast.next != null) { fast = fast.next; n --; } if (n > 0) { return listNode.next; } // 快慢指针一块儿走 while(fast.next != null) { fast = fast.next; slow = slow.next; } // 若是说被删除节点是倒数第一个节点,那么就直接置为null if (slow.next == null || slow.next.next == null) { slow.next = null; return listNode.next; } // 删除节点 slow.next = slow.next.next; return listNode.next; } }
时间复杂度:O(n),其中 n 是链表的长度,要遍历一次链表
空间复杂度:O(1)。List
方法二:遍历
class Solution { public ListNode removeNthFromEnd(ListNode head, int n) { ListNode dummy = new ListNode(0, head // 定义栈 Deque<ListNode> stack = new LinkedList<ListNode>(); ListNode cur = dummy; // 按顺序压入栈 while (cur != null) { stack.push(cur); cur = cur.next; } // 弹出 N 个元素 for (int i = 0; i < n; ++i) { stack.pop(); } // 在弹出一个(注意这里是弹出但不删除节点),做为被删除节点的前置节点 ListNode prev = stack.peek(); // 删除节点 prev.next = prev.next.next; ListNode ans = dummy.next; return ans; } }
时间复杂度:O(n),其中 n 是链表的长度,要遍历一次链表
空间复杂度: O(n),其中 n 是链表的长度。主要为栈的开销
这道题总体难度还能够,难点就是要知道如何正确的删除节点,以及若是正确的找到被删除的节点。其实删除节点还有不少办法,好比:将被删除节点的next节点的值赋给本身,而后将被删除节点的next节点删除也能够到达所要的效果。
来公众号:蘑菇睡不着,你们一块儿学习!