算法小知识-------02·03-------双指针(四)

86 阅读2分钟

这是我参与2022首次更文挑战的第11天,活动详情查看:2022首次更文挑战

双指针巩固训练的第四天

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

该题出自力扣的19题 —— 删除链表的倒数第N个节点【中等题】

审题

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

输入: head = [1,2,3,4,5], n = 2
输出: [1,2,3,5]
  • 根据题意,一个链表删除相应的倒数节点。
  • 因为是链表结构,所以遍历的缺陷会被无限放大。
  • 解决方法:
    • 计算链表长度 + List集合
      • 遍历链表,并且存进List中
      • 对指定的节点删除 = 对指定节点的上一节点的next指向下下节点
    • 双指针
      • 可以利用双指针的快慢指针
      • 两个指针分别指向链表,相差N个节点同时启动,最终快指针到达终点,慢指针则为指定删除节点

编码

    public ListNode removeNthFromEnd(ListNode head, int n) {
        //删除 n = 修改 n - 1 的next
        List<ListNode> listNodes = new ArrayList<>();
        while (head != null){
            listNodes.add(head);
            head = head.next;
        }
        int len = listNodes.size();
        int result = len - n;
        if (result >0){
            listNodes.get(result - 1).next = listNodes.get(result).next;
            return listNodes.get(0);
        }else if (result == 0 && len -1> 0){
            return listNodes.get(1);
        }else {
            return null;
        }
    }

image.png

链表的中间节点

该题出自力扣的876题 —— 链表的中间节点

审题

给定一个头结点为 head 的非空单链表,返回链表的中间结点。 如果有两个中间结点,则返回第二个中间结点。

  • 题意很简单,返回一个链表的中间节点开始的链表
  • 利用双指针的快慢指针实现
    • 两个指针同时指向链表
    • 快指针每次移动两位,慢指针每次移动1位
    • 最终快指针走到终点,慢指针就会走到一半

编码

    public ListNode middleNode(ListNode head) {
        ListNode p =head,q=head;
        while(q != null && q.next != null){
            q = q.next.next;
            p = p.next;
        }
        return p;
    }

image.png

总结

双指针的日常刷题还是较为常见的,但是也存在明显缺陷,集合需要有序。相比暴力循环,能够优化时间复杂度。