删除链表中倒数第N个节点_19

19. 删除链表的倒数第 N 个结点:https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/

 给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
复制代码
/*
1.借助栈实现
    解题思路: 
        1.通过遍历将所有的节点入栈
        2.通过for循环,弹出栈顶元素,弹出n个元素,就是需要删除的节点,
        3.此时栈顶的节点就是待删除节点的前驱节点。
*/
    
class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode dummy = new ListNode(0, head);
        Deque<ListNode> stack = new LinkedList<>();
        ListNode cur = dummy;
        while (cur != null) {
            stack.push(cur);
            cur = cur.next;
        }
        for(int i=0; i<n; i++){
            stack.pop();
        }
        ListNode prev = stack.peek();
        prev.next = prev.next.next;
        return dummy.next;
    }
}

复杂度分析:
   时间复杂度:O(L),其中 L 是链表的长度。
   空间复杂度:O(L),其中 L 是链表的长度。主要为栈的开销。
   
/*
2.通过计算链表长度
    解题思路: 
        1.第一次遍历得到链表的长度L
        2.再从头遍历,遍历到L-n+1个节点时,就是要删除的节点
        3.为了方便操作,定义虚拟头结点dummy,以及工作指针prev
           3.1 同样遍历 L - n + 1,此时下一个节点就是要删除的节点
        4.结果返回dummy.next即可
*/

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode dummy = new ListNode(0, head);
        int length = getLength(head);
        ListNode cur = dummy;
        for (int i = 1; i < length - n + 1; ++i) {
            cur = cur.next;
        }
        cur.next = cur.next.next;
        ListNode ans = dummy.next;
        return ans;
    }

    public int getLength(ListNode head) {
        int length = 0;
        while (head != null) {
            length++;
            head = head.next;
        }
        return length;
    }
}


/*
3.双指针
    解题思路: 
        1.定义两个指针p,q,都指向head
        2.让p指针先走n步
        3.之后p,q同时走,保持两者的距离相差为n.
        4.当 p 遍历到链表的末尾(即 p 为空指针)时,q 恰好指向倒数第 n 个节点。
            4.1.为了删除方便,将q指针指向虚拟头结点,其余操作不变
            4.2这样一来,当 p 遍历到链表的末尾时,q 的下一个节点就是我们需要删除的节点。
*/    
    class Solution {
        public ListNode removeNthFromEnd(ListNode head, int n) {
            ListNode dummy = new ListNode(0, head);
            ListNode first = head;
            ListNode second = dummy;
            for (int i = 0; i < n; ++i) {
                first = first.next;
            }
            while (first != null) {
                first = first.next;
                second = second.next;
            }
            second.next = second.next.next;
            ListNode ans = dummy.next;
            return ans;
        }
    }


4.递归
    class Solution {
        int cur = 0;
        public ListNode removeNthFromEnd(ListNode head, int n) {
            if (head == null) return null;
            head.next = removeNthFromEnd(head.next, n);
            return ++cur == n ? head.next : head;
        }
    }

/*
5.使用map实现
    解题思路:
        1.map第一个参数为节点的位置
        2.index初始化为1,则index++
          index初始化为0,则++index
        3.当map.size() == 1,则删除后,没有节点了,肯定返回null.
        4.当n==map.size(),表示要删除头结点,直接返回head.next.
        5.当n==1,表示要删除最后一个节点,则让map.get(map.size()-1).next=null,置空最后一个节点
        6.当n位于中间时,则定位n的前一个结点.next,指向n+1位置节点
*/
    class Solution {
        public ListNode removeNthFromEnd(ListNode head, int n) {        
         Map<Integer, ListNode> map = new HashMap<>();
            ListNode tmp = head;
            int index = 1;
            while(tmp != null){
                map.put(index++, tmp);
                tmp = tmp.next;
            }
            if(map.size() == 1) {
                return null;
            }
            if(n == map.size()) {
                return head.next;
            } else if(n == 1){
                map.get(map.size()-1).next = null;
            } else{
                map.get(map.size()-n).next = map.get(map.size()-n+2);
            }
            return head;     
        }
    }
复制代码

 

posted @   2022年总冠军gogogo  阅读(55)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
点击右上角即可分享
微信分享提示