zoukankan      html  css  js  c++  java
  • leetcode hot 100-19. 删除链表的倒数第N个节点

    19. 删除链表的倒数第N个节点

    给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。

    示例:

    给定一个链表: 1->2->3->4->5, 和 n = 2.
    当删除了倒数第二个节点后,链表变为 1->2->3->5.

    说明:

    给定的 n 保证是有效的。

    进阶:

    你能尝试使用一趟扫描实现吗?

    思路:

    快慢指针,慢指针先走n步,随后慢指针和快指针同时往后遍历,遍历到快指针为空时慢指针所指元素即使倒数第 n 个结点。

    剑指offer 14. 链表中倒数第 k 个结点的要求与本题几乎一模一样,但是这题是要删除倒数第 n 个结点,而不是直接返回倒数 第 n个结点,所以慢指针移动同时必须记录下倒数第n个结点的前一个结点。

    最后还需要特殊处理如果待删除的结点是头结点的情况,即当 pre 指针是null 时,说明待删除的结点是头结点,直接返回 head.next 

     1 class Solution {
     2     public ListNode removeNthFromEnd(ListNode head, int n) {
     3 
     4         ListNode fast = head, slow = head;
     5         for(int i = 0; i < n; i++){
     6             if(fast == null){
     7                 return null;
     8             }
     9             fast = fast.next;
    10         }
    11         ListNode pre = null;
    12         while(fast != null){
    13             fast = fast.next;
    14             pre = slow;         // 记录slow前一个结点
    15             slow = slow.next;
    16         }
    17         if(pre == null){    // 如果pre为空,说明待删除的是第一个结点
    18             return head.next;
    19         }
    20         pre.next = slow.next;   // 否则删除slow这个结点
    21         return head;
    22     }
    23 }
    leetcode 执行用时:0 ms > 100.00%, 内存消耗:36.8 MB > 56.55%

    复杂度分析:

    时间复杂度:O(n)。快指针完整的遍历了一次链表,所以时间复杂度为O(n)。
    空间复杂度:O(1)。

    思路二:借助辅助头结点

    思路参考:https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/solution/shan-chu-lian-biao-de-dao-shu-di-nge-jie-dian-b-61/

    借助辅助头结点来代替删除的是第一个结点时的特别处理,因为需要删除倒数第 n 个结点,所以需要记录倒数第 n 个结点的前一个结点,即倒数第 n + 1个结点。所以让快指针先走 n + 1步,这样当快指针为空时,慢指针所指结点就是倒数第 n + 1个结点。

    前面之所以slow指针不记录倒数第 n 个结点,而是记录倒数第 n 结点,是因为担心链表长度刚好是 n, slow指针不好赋初值,如果初值为 null, 那就没办法和 fast 一起向下遍历,如果初值为 head, 但是又担心链表刚好为(n + 1)的情况,这时如果使用 slow == head来判断待删除的结点是第一个结点就有问题。

     1 class Solution {
     2     public ListNode removeNthFromEnd(ListNode head, int n) {
     3         ListNode dummyHead = new ListNode();
     4         dummyHead.next = head;
     5         ListNode fast = dummyHead, slow = dummyHead;
     6         for(int i = 0; i < n + 1; i++){ // 快指针先走 n + 1步
     7             if(fast == null){
     8                 return null;
     9             }
    10             fast = fast.next;
    11         }
    12         while(fast != null){
    13             fast = fast.next;
    14             slow = slow.next;
    15         }
    16         slow.next = slow.next.next;   // 否则删除slow这个结点
    17         return dummyHead.next;
    18     }
    19 }
    leetcode 执行用时:0 ms > 100.00%, 内存消耗:36.1 MB > 91.46%, 空间消耗略小于思路一

    复杂度分析:

    时间复杂度:O(n)。快指针完整的遍历了一次链表,所以时间复杂度为O(n)。
    空间复杂度:O(1)。
  • 相关阅读:
    Salesforce和SAP Netweaver里数据库表的元数据设计
    Salesforce平台支持多租户Multi tenant的核心设计思路
    S/4HANA生产订单增强WORKORDER_UPDATE方法BEFORE_UPDATE参数分析
    S/4HANA生产订单的标准状态和透明工厂原型状态的映射
    1048. Find Coins (25)
    1101. Quick Sort (25)
    1009. Product of Polynomials (25)
    pta 奇数值结点链表&&单链表结点删除
    1007. Maximum Subsequence Sum (25)
    1006. Sign In and Sign Out (25)
  • 原文地址:https://www.cnblogs.com/hi3254014978/p/13907389.html
Copyright © 2011-2022 走看看