排序算法笔记-归并排序

请添加图片描述

归并排序

简介

通过找到中间值,然后递归分别从左区间和右区间找中间值,最终将所给的值划分为单个块,然后进行一步一步回溯,分块由两个单个分区排序后合成一个,以此类推,最后实现有序排序

时间复杂度

最优 nlogn
最差 n
logn

空间复杂度

O(n)

优点

归并排序是一种稳定的排序算法,且适用于各种数据情况。它的主要优点是具有稳定的时间复杂度和良好的性能。尤其是在对链表等非随机访问的数据结构进行排序时,归并排序是一种常用的选择。

解题模版

		public void mergeSort(int[] nums) {
    
    
            if (nums == null || nums.length <= 1) {
    
    
                return;
            }
            mergeSort(nums, 0, nums.length - 1);
        }

        private void mergeSort(int[] nums, int left, int right) {
    
    
            if (left >= right) {
    
    
                return;
            }

            int mid = left + (right - left) / 2;
            mergeSort(nums, left, mid);
            mergeSort(nums, mid + 1, right);
            merge(nums, left, mid, right);
        }

        private void merge(int[] nums, int left, int mid, int right) {
    
    
            int[] temp = new int[right - left + 1];
            int i = left, j = mid + 1, k = 0;

            while (i <= mid && j <= right) {
    
    
                if (nums[i] <= nums[j]) {
    
    
                    temp[k++] = nums[i++];
                } else {
    
    
                    temp[k++] = nums[j++];
                }
            }

            while (i <= mid) {
    
    
                temp[k++] = nums[i++];
            }

            while (j <= right) {
    
    
                temp[k++] = nums[j++];
            }

            System.arraycopy(temp, 0, nums, left, temp.length);
        }

练习题

88. 合并两个有序数组

模版的后半部分,使用三个指针分别指向nums1,nums2,nums1的尾部,从而进行比较赋值,换位

class Solution {
    
    
    public void merge(int[] nums1, int m, int[] nums2, int n) {
    
    
        int p1 = m-1;
        int p2 = n-1;
        int p = m+n-1;
        while(p1>=0 && p2 >= 0){
    
    
            if(nums1[p1] >nums2[p2]){
    
    
                nums1[p] = nums1[p1];
                p1--;
            }else{
    
    
                nums1[p] = nums2[p2];
                p2--;
            }
            p--;
        }
        while(p2>=0){
    
    
            nums1[p] = nums2[p2];
            p2--;
            p--;
        }
    }
}
  1. 排序链表
    同样的思路放在链表中,通过找到中间值,然后将其中间值下一个指向空值,将链表分成两个,以此类推,分成n份,之后在重新连接,最终形成一个新的排序好的链表

class Solution {
    
    
    public ListNode sortList(ListNode head) {
    
    
        if(head == null || head.next == null){
    
    
            return head;
        }
        ListNode mid = findMiddle(head);
        ListNode midNext = mid.next;
        mid.next = null;
        ListNode left = sortList(head);
        ListNode right = sortList(midNext);
        return merge(left,right);
    }
    private ListNode findMiddle(ListNode head){
    
    
        ListNode slow = head;
        ListNode fast = head.next;
        while(fast!= null && fast.next != null){
    
    
            slow = slow.next;
            fast = fast.next.next;
        }
        return slow;
    }
    private ListNode merge(ListNode l1,ListNode l2){
    
    
        ListNode dummy = new ListNode(-1);
        ListNode curr = dummy;
        while(l1 != null && l2 != null){
    
    
            if(l1.val <l2.val){
    
    
                curr.next = l1;
                l1 = l1.next;
            }else{
    
    
                curr.next  = l2;
                l2 = l2.next;
            }
            curr = curr.next;
        }
        if(l1 != null){
    
    
            curr.next = l1;
        }
        if(l2 != null){
    
    
            curr.next = l2;
        }
        return dummy.next;
    }
}

颜色分类
这个题可以i当做所有排序算法的练习题,使用归并排序,直接套用模版即可

public void sortColors(int []nums){
    
    
        if(nums == null || nums.length <=1){
    
    
            return;
        }
        mergeSort(nums,0,nums.length-1);
    }
    public void mergeSort(int [] nums,int left,int right){
    
    
        if(left>=right){
    
    
            return;
        }
        int mid = left+(right-left)/2;
        mergeSort(nums,left,mid);
        mergeSort(nums,mid+1,right);
        merge(nums,left,mid,right);
    }
    private void merge(int []nums,int left,int mid ,int right){
    
    
        int []temp = new int[right-left+1];
        int i = left,j = mid+1,k=0;
        while(i<=mid && j<= right){
    
    
            if(nums[i]<=nums[j]){
    
    
                temp[k++] = nums[i++];
            }else{
    
    
                temp[k++] = nums[j++];
            }
        }
        while(i<=mid){
    
    
            temp[k++] = nums[i++];
        }
        while(j<= right){
    
    
            temp[k++] = nums[j++];
        }
        System.arraycopy(temp,0,nums,left,temp.length);
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_54174102/article/details/131695767