zoukankan      html  css  js  c++  java
  • 【力扣】148. 排序链表

    给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。

    进阶:

    你可以在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序吗?
     

    示例 1:


    输入:head = [4,2,1,3]
    输出:[1,2,3,4]
    示例 2:


    输入:head = [-1,5,3,4,0]
    输出:[-1,0,3,4,5]
    示例 3:

    输入:head = []
    输出:[]
     

    提示:

    链表中节点的数目在范围 [0, 5 * 104] 内
    -105 <= Node.val <= 105

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/sort-list
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

    简单做法:

    public ListNode sortList(ListNode head) {
            if(head == null || head.next == null){
                return head;
            }
            List<ListNode> list = new ArrayList<ListNode>();
            while(head != null){
                list.add(head);
                head = head.next;
            }
            Collections.sort(list,(item1,item2) -> (item1.val - item2.val));
            for(int i = 1; i < list.size(); i++){
                list.get(i-1).next = list.get(i);
            }
            list.get(list.size() -1 ).next = null;
            return list.get(0);
        }
    //首先先用昨天的题目的排序方式写一遍、发现时间超限
        public ListNode sortList(ListNode head) {
    
            if(head == null || head.next == null){
                return head;
            }
            //我们使用 fast,slow 快慢双指针法,奇数个节点找到中点,偶数个节点找到中心左边的节点。
            ListNode fast = head.next;
            ListNode slow = head;
            while(fast != null && fast.next != null){
                fast = fast.next.next;
                slow = slow.next;
            }
            //将链表分割,分为左边和右边
            ListNode temp = slow.next;
            slow.next = null;//分割需要设置为null
    
            ListNode left = sortList(head);
            ListNode right = sortList(temp);
    
            //进行左边和右边链表的整和
            ListNode h = new ListNode();
            ListNode result = h;
    
            //这个循环没有问题
            while(left != null && right != null){
                if(left.val < right.val){
                    h.next = left;
                    left = left.next;
                }else {
                    h.next = right;
                    right = right.next;
                }
                h = h.next;
            }
            //这里有一些疑问: h.next = left  || h.next = right  为什么要这么设置,这两种设置效果是一样的
            //因为在循环结束时,有可能因为right为空了,或者left为空了,导致没有给h.next 赋值,所以,再这里复制。
            h.next = right != null ? right : left;
    
            return result.next;
        }
    

    时间复杂度:O(logn)

    空间复杂度:O(logn)

    以上算法的整体思想是:找到中心点,将链表分割,将分割后的链表排序,最后合并.

    一个入行不久的Java开发,越学习越感觉知识太多,自身了解太少,只能不断追寻
  • 相关阅读:
    PHP面试:实现动态获取函数参数的方法
    PHP面试:什么是类的多态性,请写出一个例子
    php相关操作
    客户端app支付宝登录接口
    商品分类设计
    Git连接远程服务器
    iptables/mysql设置指定主机访问指定端口
    CMake安装grpc生成gRPCTargets.cmake文件
    Linux下Springboot解决`APR based Apache Tomcat Native library`提示
    java双重检测或枚举类实现线程安全单例(懒汉模式)
  • 原文地址:https://www.cnblogs.com/fengtingxin/p/14015927.html
Copyright © 2011-2022 走看看