手撸代码-删除链表的倒数第n个节点

描述

给定一个链表,删除链表的倒数第 nn 个节点并返回链表的头指针
例如,
给出的链表为: 1→2→3→4→5, n= 2n=2.
删除了链表的倒数第 n 个节点之后,链表变为1→2→3→5.

备注:

题目保证 nn 一定是有效的
请给出时间复杂度为 O(n) 的算法

解法一:

将链表存入Map中,通过索引快速找到要删除的结点,要注意头尾结点的删除的特殊性

public ListNode removeNthFromEnd (ListNode head, int n) {
    
    
        // write code here
        Map<Integer,ListNode> nodes = new HashMap<>();
        ListNode tmp = head;
        int idx = 0;
        while(tmp != null) {
    
    
            nodes.put(idx++, tmp);
            tmp = tmp.next;
        }
        
        // 删除头节点,注意只有一个节点的链表
        int idx2Del = idx - n;
        if (idx2Del == 0 && idx > 1) {
    
    
            return nodes.get(1);
        } else if (idx2Del == 0) {
    
    
            return null;
        }
        
        ListNode nodePre = nodes.get(idx2Del-1);
        
        // 如果删除的是尾节点
        ListNode nodeNext = null;
        
        // 如果不是尾节点
        if (n > 1) {
    
    
            nodeNext = nodes.get(idx2Del+1);
        }
        
        nodePre.next = nodeNext;
        return nodes.get(0);
        
    }

解法二:

  • 1,双指针,先移动fast指针,使其与slow指针相差n个结点
  • 2,slow最终指向要删除的结点的前一个结点,fast指向尾结点
  • 3,临界点的考虑非常重要:只有一个结点,只有两个结点,如果删除的是头结点,如果删除的是尾结点
        ListNode slow = head;
        ListNode fast = head;
        int idx = 0;
        while(fast.next != null) {
    
    
            if (idx++ < n) {
    
    
                fast = fast.next;
            } else {
    
    
                slow = slow.next;
                fast = fast.next;
            }
        }
       
        // 如果是删除头节点
        if (idx + 1 == n) {
    
    
            return slow.next;
        }
        
        // 如果是删除其他节点
        slow.next = slow.next.next;
       
        return head;

Guess you like

Origin blog.csdn.net/epitomizelu/article/details/119976331