删除链表的倒数第n个节点
给定一个链表,删除链表的倒数第 nn 个节点并返回链表的头指针

示例
输入:{1,2},2
返回值:{2}

方法一 存入集合模拟

将所有元素存入vector中获取倒数第n的位置将其转换,但倒数第一个和正数第一个需要特判一下
图片说明

代码

 ListNode* removeNthFromEnd(ListNode* head, int n) {
        // write code here
        ListNode *now = head;
        vector<ListNode*> arr;
        while(now){    //遍历一遍链表
            arr.push_back(now);
            now = now->next;
        }
        if(n == 1){ //特判如果是倒数第一个
            if(arr.size() > 1){ //如果链表长度大于1
                arr[arr.size() - 2]->next = NULL;
            }else return NULL; //如果等于一则删除列表就为空
            return head;
        }
        if(n == arr.size()){    //如果是删除第一个则直接返回第一个的下一个
            return arr[1];
        }
        int s = arr.size() - n;
        arr[s - 1]->next = arr[s + 1];
        return head;
    }

时间复杂度 O(n) 遍历一遍链表
空间复杂度 O(n) vector存储了整个链表开辟O(n)的空间

方法二 双指针

创建两个listNode 分别执行 当前遍历到的结点和当前结点的倒数第n + 1 个点结点,但不理完后即可直接更新,和方法一一样需要特判一下n是最后一个还是第一个。
图片说明
代码

ListNode* removeNthFromEnd(ListNode* head, int n) {
        // write code here
        ListNode *now = head;
        ListNode *ls = head, *rs = head;
        int cnt = 0;
        int sum = 0;
        while(now){    //遍历链表
            sum ++;
            now = now->next;
            if(cnt > n){    //维护两个指针的距离为n + 1
                cnt --;
                ls = ls->next;
            }
            cnt ++;
        }
        if(sum == n){    //如果是删除第一个
            return head->next;
        }else if(n == 1){    //删除最后一个
            ls->next = NULL;
        }else 
            ls->next = ls->next->next;

        return head;
    }

时间复杂度: O(n) 遍历整个链表
空间复杂度: O(1) 使用了若干个变量