912排序数组

题目描述

给一个整数数组nums,将该数组升序排列。

提示

  • 1 <= nums.length <= 50000
  • 50000 <= nums[i] <= 5000

思路分析

力扣官方给大家提醒,要掌握各种排序方法。

  1. 冒泡。从左到右依次比较相邻元素,前大于后则交换,每次冒泡保证最后一个元素是当前最大,再遍历前 n-1 个元素。
  2. 选择。找出前 n 个元素中max,与最后一个元素交换,再找前 n-1 个元素和第 n-1 个元素交换,以此类推。
  3. 插入。遍历数组,保证当前元素左边的数组有序,将当前元素插入对应位置。
  4. 归并。分治思想,把数组划分为一个一个小块,再分别排序,然后两两合并。合并时,需要用一个辅助数组存储排序后的序列。
  5. 计数。当整数范围不大时使用。创建一个长度为max-min的数组,统计所有元素出现的次数,再根据次数把元素放回数组,实现排序。
  6. 桶排。把所有的元素放在一个一个的桶中(看成区间),把每个桶里的元素排序,最后把桶中元素倒出就是排列好的数组。
  7. 快排。这里避免发生极端情况,使用随机快排。取最后一个元素 right 作为分界点,把整个数组分为两块/三块,左边的元素小于分界点,右边的元素大于分界点,把分界点移到中间。再对左边和右边分别进行相同的操作。

代码实现

    public int[] sortArray(int[] nums) {
        if (nums.length < 2) {
            return nums;
        }
        quickSort(nums, 0, nums.length - 1);
        bubbleSort(nums);
        selectSort(nums);
        insertSort(nums);
        mergeSort(nums, 0, nums.length - 1);
        bucketSort(nums);
        return nums;
    }

    //冒泡排序
    public void bubbleSort(int[] nums) {
        for (int i = nums.length - 1; i >= 1; i--) {
            for (int j = 1; j <= i; j++) {
                if (nums[j - 1] > nums[j]) {
                    swap(nums, j - 1, j);
                }
            }
        }
    }

    //选择排序 每次找出n个元素的max放在最后的位置,之后n--
    public void selectSort(int[] nums) {
        for (int i = nums.length - 1; i >= 1; i--) {
            int max = 0;
            for (int j = 0; j <= i; j++) {
                max = nums[j] > nums[max] ? j : max;
            }
            swap(nums, i, max);
        }
    }

    //插入排序
    public void insertSort(int[] nums) {
        for (int i = 1; i < nums.length; i++) {
            int j = i;
            while (j > 0 && nums[j] > nums[j - 1]) {
                swap(nums, j, j - 1);
                j--;
            }
        }
    }

    //归并排序
    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, right, mid);
    }

    public void merge(int[] nums, int left, int right, int mid) {
        int[] help = new int[right - left + 1];
        int p1 = left, p2 = mid + 1;
        int cur = 0;
        while (p1 <= mid && p2 <= right) {
            help[cur++] = nums[p1] <= nums[p2] ? nums[p1++] : nums[p2++];
        }
        while (p1 <= mid) {
            help[cur++] = nums[p1++];
        }
        while (p2 <= right) {
            help[cur++] = nums[p2++];
        }

        for (int i = 0; i < help.length; i++) {
            nums[left + i] = help[i];
        }
    }

    //计数排序
    public void countSort(int[] nums) {
        int min = Integer.MIN_VALUE;
        int max = Integer.MAX_VALUE;
        for (int num : nums) {
            min = Math.min(num, min);
            max = Math.max(num, max);
        }
        int[] count = new int[max - min + 1];
        for (int num : nums) {
            count[num - min]++;
        }
        int cur = 0;
        for (int i = 0; i < count.length; i++) {
            while (count[i] > 0) {
                nums[cur++] = i + min;
                count[i]--;
            }
        }
    }

    //桶排
    public void bucketSort(int[] nums) {
        //桶大小
        int size = 100;
        int min = Integer.MIN_VALUE;
        int max = Integer.MAX_VALUE;
        for (int num : nums) {
            min = Math.min(num, min);
            max = Math.max(num, max);
        }

        int count = max - min + 1;
        int bucketSize = count % size == 0 ? count / size : count / size + 1;
        List<Integer>[] buckets = new List[bucketSize];
        //将所有元素入桶
        for (int num : nums) {
            int quo = (num - min) / size;
            if (buckets[quo] == null) {
                buckets[quo] = new ArrayList<>();
            } else {
                buckets[quo].add(num);
            }
        }

        int cur = 0;
        for (List<Integer> bucket : buckets) {
            if (bucket != null) {
                bucket.sort(null);
                for (Integer integer : bucket) {
                    nums[cur++] = integer;
                }
            }
        }
    }

    //随机快排
    public void quickSort(int[] nums, int left, int right) {
        if (left < right) {
            //随机快排
            swap(nums, right, left + (int) (Math.random() * (right - left + 1)));

            int[] p = process(nums, left, right);
            quickSort(nums, left, p[0] - 1);
            quickSort(nums, p[1] + 1, right);
        }
    }

    public int[] process(int[] nums, int left, int right) {
        int less = left - 1;
        int more = right;
        while (left < more) {
            if (nums[left] < nums[right]) {
                swap(nums, left++, ++less);
            } else if (nums[left] > nums[right]) {
                swap(nums, left, --more);
            } else {
                left++;
            }
        }
        swap(nums, right, more);
        return new int[]{less + 1, more};
    }


    public void swap(int[] nums, int a, int b) {
        int tmp = nums[a];
        nums[a] = nums[b];
        nums[b] = tmp;
    }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值