链表&双指针

234 阅读2分钟

前言

“这是我参与8月更文挑战的第5天,活动详情查看:8月更文挑战

总结下链表结合双指针的问题

  1. NC69 链表中倒数最后k个结点(中等)
  2. NC53 删除链表的倒数第n个节点(中等)

链表中倒数最后k个结点

描述: 输入一个链表,输出一个链表,该输出链表包含原链表中从倒数第k个结点至尾节点的全部节点。

如果该链表长度小于k,请返回一个长度为 0 的链表。

思路分析:

  • 遍历一遍链表统计节点数, 找到index 为 len - k 的节点(index 从 0 开始), 注意 k > len 直接返回 空链表
  • 双指针,fast 指针先走 k步, 然后 slow 指针 指向头节点, fast 和 slow 一起向后移动 直到 fast 为 null 时, slow 指向的就是倒数第 k 个节点

AC 代码:

遍历版本:

    public ListNode FindKthToTail (ListNode pHead, int k) {
        // write code here
        if(pHead == null) return null;
        int count = 1;
        ListNode cur = pHead;
        while(cur.next != null){
            count++;
            cur = cur.next;
        }
        
        if(k > count) return null;
        
        int index = count - k;
        int i = 0;
        cur = pHead;
        while(i != index){
            cur = cur.next;
            i++;
        }
        return cur;
    }

双指针版本:

    public ListNode FindKthToTail (ListNode pHead, int k) {
        // write code here
        if(pHead == null) return null;
        ListNode slow = pHead;
        ListNode fast = pHead;
        
        while(k != 0){
            if(fast == null){
                return null;
            }
            fast = fast.next;
            k--;
        }
        
        while(fast != null){
            fast = fast.next;
            slow = slow.next;
        }
        
        return slow;
    }

删除链表的倒数第n个节点

描述:给定一个链表,删除链表的倒数第 n 个节点并返回链表的头指针 例如,

给出的链表为:1→2→3→4→5, n=2 删除了链表的倒数第 n 个节点之后,链表变为 1→2→3→5.

备注:题目保证 n 一定是有效的

思路分析: 整体上思路和上一道题一样, 利用双指针找到倒数第 k 个节点, 不同的是这个需要删除倒数第k个节点,因此需要知道倒数第 k个节点的前置节点, 因为删除的可能是头节点,所以添加一个虚拟的头节点(pre),fast 指针先走 k步,pre 和 fast 一起向后移动, 当 fast 为空时, pre 指向的正是 倒数第k个节点的前置节点

AC代码:

    public ListNode removeNthFromEnd (ListNode head, int n) {
        // write code here
        ListNode pre = new ListNode(-1);
        pre.next = head;
        ListNode ans = pre;
        
        ListNode fast = head;
        
        while(n != 0){
            fast = fast.next;
            n--;
        }
        
         while(fast != null){
            fast = fast.next;
            pre = pre.next;
        }
        
        pre.next = pre.next.next;
        return ans.next;
        
    }