LeetCode刷题系列 -- 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
 

思路:

利用归并排序来实现

可以利用递归来实现,分成两步:

1、定义快慢指针,从中间将链表截断,分成两段,递归将链表截成两段,直到 head.next == null 为止

2、将两个已经排序好的子链表 merge 成一个新的链表(即有将两个有序链表合并成一个有序链表)

Java代码如下:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode sortList(ListNode head) {

        if(head.next == null){
            return head;
        }

        ListNode slow = head;
        ListNode fast = head;

        while (fast!=null&&fast.next!=null){
            slow = slow.next;
            fast = fast.next.next;
        }
        ListNode  newHead = slow.next;
        slow.next = null;  // 断开中间节点链表
        sortList(head);
        sortList(newHead);
        merge(head,newHead);
        
        return head;

    }

    //两个有序链表合并
    public ListNode  merge(ListNode left,ListNode right){

        if(left==null){
            return right;
        }
        if(right == null){
            return left;
        }

        if(left.val<right.val){
            left.next = merge(left.next,right);
            return left.next;
        }else {
            right.next = merge(left,right.next);
            return right.next;
        }

    }
   // 合并链表非递归方式
    public ListNode mergeTwoLists1(ListNode l1, ListNode l2) {
        ListNode beforeHead = new ListNode(0);

        ListNode tmp = beforeHead;

        while (l1!=null && l2!=null){
            if(l1.val<l2.val){
                tmp.next = l1;
                l1 = l1.next;
            }else {
                tmp.next = l2;
                l2 = l2.next;
            }
            tmp = tmp.next;
        }

        tmp.next = l1!=null?l1:l2;

        return beforeHead.next;


    }

}

c++

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* sortList(ListNode* head) {
        if(head == nullptr) {
            return nullptr;
        }
        vector<ListNode*> node_vec;

        ListNode* curr = head;
        while(curr != nullptr) {
            node_vec.emplace_back(curr);
            curr = curr->next;
        }

        mergeSort(node_vec,0,node_vec.size()-1);

        for(int i=0;i<node_vec.size()-1;i++) {
            node_vec[i]->next = node_vec[i+1];
        }

        node_vec[node_vec.size()-1]->next = nullptr;

        return node_vec[0];
    }

    void mergeSort(vector<ListNode*>& node_vec, int left, int right) {
          if(left >= right) {
              return;
          }

          int mid = left + (right-left)/2;

          mergeSort(node_vec,left,mid);
          mergeSort(node_vec,mid+1,right);
          merge(node_vec,left,mid,right);  
    }

    void merge(vector<ListNode*>& node_vec, int left, int mid, int right) {
        vector<ListNode*> tmp_vec; // 用于临时存放排序后的节点

        int ll = left;
        int mm = mid+1;

        while(ll<=mid && mm<=right) {
            if(node_vec[ll]->val < node_vec[mm]->val) {
                tmp_vec.emplace_back(node_vec[ll++]);
            } else {
                tmp_vec.emplace_back(node_vec[mm++]);
            }
        }

        while(ll<=mid) {
            tmp_vec.emplace_back(node_vec[ll++]);
        }

        while(mm<=right) {
            tmp_vec.emplace_back(node_vec[mm++]);
        }

        for(int i=left;i<=right;i++) {
            node_vec[i] = tmp_vec[i-left];
        }
    }

};

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值