• 【链表问题】打卡3:删除单链表的中间节点


    前言

    以专题的形式更新刷题贴,欢迎跟我一起学习刷题,相信我,你的坚持,绝对会有意想不到的收获。每道题会提供简单的解答,如果你有更优雅的做法,欢迎提供指点,谢谢

    【题目描述】

    给定链表的头节点head,实现删除链表的中间节点的函数。

      例如:

      步删除任何节点;

      1->2,删除节点1;

      1->2->3,删除节点2;

      1->2->3->4,删除节点2;

      1->2->3->4-5,删除节点3;

    【要求】

    如果链表的长度为 N, 时间复杂度达到 O(N), 额外空间复杂度达到 O(1)

    【难度】

    士:★☆☆☆

    【解答】

    这道题要求删除中间节点,我们可以采用双指针的方法来做,就是用一个快指针和一个慢指针,快指针每次前进两个节点,而慢指针每次前进一个节点。当快指针遍历完节点时,慢指针刚好就在中间节点了。之前写过一篇一些算法的常用技巧也有所过指针使用的一些技巧。

    不过在做的时候,最好是先把一些特殊情况先处理好,例如删除的可能是第一个节点,也有可能不用删除节点(只有一个节点时就不用删除了。

    代码如下

        public static Node removeMidNode(Node head) {
            if(head == null || head.next == null)
                return head;
            if (head.next.next == null) {
                return head.next;
            }
            Node fast = head.next.next;//快指针
            Node slow = head;//慢指针
    
            //slow最终指向中间节点的前驱
            while (fast.next != null && fast.next.next != null) {
                slow = slow.next;
                fast = fast.next.next;
            }
            //进行删除
            slow.next = slow.next.next;
            return head;
        }
    

    上次拿到删除倒数第 K 个节点的题其实也是可以使用双指针的,但个人认为,那道题使用双指针的方法并没有我上次那个做法优雅,而这次删除中间节点,则用双指针比较优雅。至于原因,可以自己打下代码看看

    问题拓展

    题目:删除链表中 a / b 处的节点

    【题目描述】

      给定链表的头节点 head、整数 a 和 b,实现删除位于 a/b 处节点的函数。

      例如:

      链表:1->2->3->4->5,假设 a/b 的值为 r。

      如果 r = 0,不删除任何节点;

      如果 r 在区间 (0,1/5] 上,删除节点 1;

      如果 r 在区间 (1/5,2/5] 上,删除节点 2;

      如果 r 在区间 (2/5,3/5] 上,删除节点 3;

      如果 r 在区间 (3/5,4/5] 上,删除节点 4;

      如果 r 在区间 (4/5,1] 上,删除节点 5;

      如果 r 大于 1,不删除任何节点。

    【要求】

    如果链表的长度为 N, 时间复杂度达到 O(N), 额外空间复杂度达到 O(1)

    【难度】

    士:★☆☆☆

    【解答】

    可以自己动手做一下或者想一下,如果想要获取答案,可以在公众号回复 解答1 获取代码。

        //这道题可以转换为删除第 K = (a * n / b)个节点。其中n表示链表节点
        //的个数,但由于(a * n / b)有可能出现小数,所以我们取 K的上限。
        //所谓上限就是大于等于K的最小整数。
        public static Node removeByRatio(Node head, int a, int b) {
            if(a < 1 || a > b)
                return head;
            int n = 0;
            Node cur = head;
            //统计一共有多少个节点
            while (cur != null)
                n++;
            //问题转换为删除第K个节点,取(a * n / b)的整数上限
            int K =  (int)Math.ceil((double)(a * n) / (double)b);
            if(K == 1)
                return head.next;
            if (K > 1) {
                cur = head;
                //定位到第K个节点的前驱
                while (--K != 1) {
                    cur = cur.next;
                }
                cur.next = cur.next.next;
            }
            return head;
        }
    
    

    最后推广下我的公众号:苦逼的码农,文章都会首发于我的公众号,期待各路英雄的关注交流。

  • 相关阅读:
    iOS 10 的一个重要更新-用 UIViewPropertyAnimator 编写动画
    iOS 10 的一个重要更新-线程竞态检测工具 Thread Sanitizer
    iOS 10 的一个重要更新-开发 iMessage 的第三方插件
    状态栏白色
    iOS 对 HTTPS 证书链的验证
    Xcode8 带来的新特性和坑
    升级cocoapods1.1.1版本
    (这也不是,那也不是,怎么办?)无论何时坚持自己的原则,当选准了目标,就不放弃,做最好的自己。我们必须要有一定的看法,正确的做法;有时,我们无法避免他人在旁的批评或劝告,但我们是无法取悦每个人的,否则将失去了方向,迷失了自己。
    笑话集锦(1)
    最感动的一首现代诗(转)(修正了一点翻译)
  • 原文地址:https://www.cnblogs.com/kubidemanong/p/10426961.html
Copyright © 2020-2023  润新知