zoukankan      html  css  js  c++  java
  • 【LeetCode-链表】删除链表的倒数第N个节点

    题目描述

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

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

    说明:
    给定的 n 保证是有效的。
    进阶:
    你能尝试使用一趟扫描实现吗?
    题目链接https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/

    思路1

    链表倒数第 n 个节点就是正数的第 len-n 个节点,其中 len 为链表长度。所以,先遍历链表一遍求长度 len,然后在遍历到链表的第 len-n 个节点前执行删除操作。需要注意的是,由于删除的可能是链表的第一个节点,所以需要使用一个新的链表头(哑结点)指向原来的链表。代码如下:

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    class Solution {
    public:
        ListNode* removeNthFromEnd(ListNode* head, int n) {
            if(head==nullptr) return nullptr;
    
            int len = getLen(head);
            ListNode* dummyHead = new ListNode(0);
            dummyHead->next = head;
            ListNode* curNode = dummyHead;
            for(int i=0; i<len-n; i++){ // 循环 len-n 次,得到原链表中第 len-n-1 个节点(编号从 1 开始)
                curNode = curNode->next;
            }
            curNode->next = curNode->next->next;
    
            return dummyHead->next;
        }
    
        int getLen(ListNode* head){
            int len = 0;
            while(head!=nullptr){
                len++;
                head = head->next;
            }
            return len;
        }
    };
    
    • 时间复杂度:O(n)
    • 空间复杂度:O(1)

    思路2

    使用两个指针 p1, p2. p1 和 p2 初始都指向哑结点 dummyHead,然后 p2 先走 n 步,然后 p1 和 p2 共同往后走,当 p2->next==nullptr 时停止移动两个指针,此时 p1->next 就是倒数第 n 个节点。代码如下:

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    class Solution {
    public:
        ListNode* removeNthFromEnd(ListNode* head, int n) {
            if(head==nullptr) return nullptr;
    
            ListNode* dummyHead = new ListNode(0);
            dummyHead->next = head;
            ListNode* p1 = dummyHead;
            ListNode* p2 = dummyHead;
            for(int i=0; i<n; i++) p2 = p2->next;
            while(p2->next!=nullptr){
                p1 = p1->next;
                p2 = p2->next;
            }
            p1->next = p1->next->next;
            return dummyHead->next;
            
        }
    };
    
    • 时间复杂度:O(n)
    • 空间复杂度:O(1)

    总结

    这个问题的难点在于不好确定应该移动几步,例如思路 2 中,p2 是先移动 n 步,还是 n-1 步或者 n+1 步。遇到这种问题,可以在纸上画出来分析一下,可以很快得出答案。

  • 相关阅读:
    python中os.listdir( )函数读取文件夹
    斐讯k2p 月光银 硬件版本A2-软件版本22.7.8.5 刷官改系统
    Ubuntu 16.04 换国内源
    pip和apt-get换源
    Python-OpenCV中的filter2D()函数
    Python-OpenCV中图像合并显示
    Python-OpenCV——Image Blurring(Image Smoothing)
    Python-OpenCV中的resize()函数
    删除Chrome地址栏记录中自动补全的网址
    Python中Numpy mat的使用
  • 原文地址:https://www.cnblogs.com/flix/p/13096109.html
Copyright © 2011-2022 走看看