【力扣】19. 删除链表的倒数第 N 个结点
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
进阶:你能尝试使用一趟扫描实现吗?
示例 1:
输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]
示例 2:输入:head = [1], n = 1
输出:[]
示例 3:输入:head = [1,2], n = 1
输出:[1]
提示:
链表中结点的数目为 sz
1 <= sz <= 30
0 <= Node.val <= 100
1 <= n <= sz
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
//最先找到的方案:先找到这个链表有多长,然后找到应该移除的节点。 public ListNode removeNthFromEnd(ListNode head, int n) { //先找到这个链表有多长 ListNode pre = new ListNode(-1,head); //这里pre的作用就是一个哑节点,标识从哪里开始 int length = 0; ListNode cur = head; while(cur != null){ length++; cur = cur.next; } if(length < n){ return pre.next; } //这里为什么要设置 cur = pre? cur = pre; //为什么length - n + 1 //举个例子:我们要length = 5 我们要去掉倒数第二个节点,那么这个节点正数应该是第4个 所以是 5-2+1; //其次,我们要找到的正数第四个节点,而是应该找到正数第三个节点 //所以从1开始,且小于length - n + 1 for(int i = 1; i< length - n + 1; i++){ cur = cur.next; } //当前已经找到cur cur.next = cur.next.next; return pre.next; }
优点:这是最容易想到的方案,劣势也很清楚,遍历了两次
时间复杂度:O(n)
空间复杂度:O(1)
如何将遍历次数减少到一次呢?
那就要借助双指针了:
//第二个方案:使用双指针 //1.执行一次遍历,找到n在哪个位置 这是第一个指针 //2.执行第二次遍历,第一个指针指向结束,第二个指针指向当前节点 public ListNode removeNthFromEnd(ListNode head, int n) { // ListNode pre = new ListNode(-1,head); //这里pre的作用就是一个哑节点,标识从哪里开始 ListNode first = head; //第一个指针 //第一次遍历到第n个结束 for(int i = 1; i<= n; i++){ first = first.next; } ListNode second = pre; //第二个指针 //第二次遍历,遍历到第一个指针结束为止 while(first != null){ second = second.next; first = first.next; } second.next = second.next.next; return pre.next; }
一个入行不久的Java开发,越学习越感觉知识太多,自身了解太少,只能不断追寻