• [LeetCode] 148. Sort List Java


    题目:Sort a linked list in O(n log n) time using constant space complexity.

    题意及分析:要求使用o(nlogn)的时间复杂度和o(1)的空间复杂度将链表排序。o(nlogn)的排序算法有快速排序,归并排序和堆排序。但是快速排序最差情况下时间复杂度为o(n^2),所以不考虑,堆排序比较复杂,因此我这里使用归并排序。对于一个数组来说,归并排序主要是讲数组从中间分割成两部分,然后对左右子数组做同样操作,直至每个子数组都只有一个元素,然后两两合并。因为这里是链表,所以怎么找到中间分割点比较关键,这里使用两个指针slow,fast,slow每次移动一步,fast每次移动两步,当fast到链表尾时,slow所在位置就是链表中。我这里使用的是递归的方法求解。对于链表来说,非递归算法效率更高,所以合并处可以使用非递归算法,这样会快很多。

    代码:

    递归:

    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) { val = x; }
     * }
     */
    public class Solution {
        public ListNode sortList(ListNode head) {
    		 if(head==null||head.next==null) return head;
    		 
    		 ListNode slow=head;
    		 ListNode fast=head;
    		 ListNode p=head;
    		 
    		 while(fast!=null&&fast.next!=null){		//slow每次走一步,fast每次走两步,当fast走到最后时,slow走到链表的中间,这样就可以将链表分成两半
    			 p=slow;
    			 slow=slow.next;
    			 fast=fast.next.next;
    		 }
    		 p.next=null;		//将前半段链表设置为null结尾,这样链表就被分成(head,p),(slow,fast)
    		 
    		 ListNode h1=sortList(head);
    		 ListNode h2=sortList(slow);
    		 
    		 return mergeList(h1, h2);
    	 }
    		 
    	 public ListNode mergeList(ListNode h1,ListNode h2){		//合并两个链表
    		if(h1==null) return h2;
    		if(h2==null) return h1;
    		if(h1.val<h2.val){
    			h1.next=mergeList(h1.next, h2);
    			return h1;
    		}else{
    			h2.next=mergeList(h1, h2.next);
    			return h2;
    		}
    	 }
    }
    

     非递归:

    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) { val = x; }
     * }
     */
    public class Solution {
        public ListNode sortList(ListNode head) {
    		 if(head==null||head.next==null) return head;
    		 
    		 ListNode slow=head;
    		 ListNode fast=head;
    		 ListNode p=head;
    		 
    		 while(fast!=null&&fast.next!=null){		//slow每次走一步,fast每次走两步,当fast走到最后时,slow走到链表的中间,这样就可以将链表分成两半
    			 p=slow;
    			 slow=slow.next;
    			 fast=fast.next.next;
    		 }
    		 p.next=null;		//将前半段链表设置为null结尾,这样链表就被分成(head,p),(slow,fast)
    		 
    		 ListNode h1=sortList(head);
    		 ListNode h2=sortList(slow);
    		 
    		 return mergeList(h1, h2);
    	 }
    		 
    	 public ListNode mergeList(ListNode h1,ListNode h2){		//合并两个链表
    		if(h1==null) return h2;
    		if(h2==null) return h1;
    		ListNode res = new ListNode(0);		//结果链表
    		ListNode x=res;
    		while(h1!=null&&h2!=null){
    			if(h1.val<h2.val){
    				x.next=h1;
    				h1=h1.next;
    				x=x.next;
    			}else{
    				x.next=h2;
    				h2=h2.next;
    				x=x.next;
    			}
    		}
    		if(h1!=null)
    			x.next=h1;
    		if(h2!=null)
    			x.next=h2;
    		
    		return res.next;
    	 }
    }
    

      

      

      

  • 相关阅读:
    考研笔记-物理层协议
    考研笔记-数据链路层和局域网
    考研笔记-网络层和路由
    考研笔记-运输层服务和工作原理
    考研笔记-应用层
    考研笔记-数据通信技术基础
    考研笔记-计算机网络协议和体系结构
    计算机网络复习(一)
    “百度杯”CTF比赛 十月场_GetFlag(验证码爆破+注入+绝对路径文件下载)
    “技术产品”面向市场的表达方法思辨——BY Me
  • 原文地址:https://www.cnblogs.com/271934Liao/p/7092968.html
Copyright © 2020-2023  润新知