Java教程

Leetcode--Java--912. 排序数组

本文主要是介绍Leetcode--Java--912. 排序数组,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

题目描述

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

样例描述

示例 1:

输入:nums = [5,2,3,1]
输出:[1,2,3,5]
示例 2:

输入:nums = [5,1,1,2,0,0]
输出:[0,0,1,1,2,5]

思路

手撕堆排序

  1. 堆调整,先将整个数组调整为最大堆,就是从末尾开始来调整,使得满足最大堆的性质:父节点大于两个儿子结点
  2. 调整的具体实现:从当前结点开始往下调整,找出左右孩子结点较大的再和父节点比较,如果比父节点大,就交换,否则直接退出。迭代当前结点为孩子结点,只要在范围内就继续遍历
  3. 调整,从最后一个非叶子结点(len - 1 / 2)开始调整

代码

class Solution {
    public int[] sortArray(int[] nums) {
        int len = nums.length;
        //先调整一遍,整理成堆
        heapify(nums);
        //循环保证,[0, i]堆有序
        for (int i = len - 1; i >= 1; ) {
            //将堆顶元素换到末尾
            swap(nums, 0, i);
            //下次待排序区间为[0, i - 1],逐步减少堆有序的部分
            i --;
            //调整刚加入到堆顶的元素,让堆整体满足最大堆性质
            siftDown(nums, 0, i);
        }
        return nums;
    }

    public void heapify(int []nums) {
        int len = nums.length;
        //从第一个非叶子结点位置(len - 1 / 2)开始调整,每次调整的范围是[i, len - 1] 
        for (int i = (len - 1) / 2; i >= 0; i -- ) {
            siftDown(nums, i, len - 1);
        }
    }

    public void siftDown(int []nums, int k, int end) {
        //k为当前位置,end为最大的范围
        //先判断左儿子是否在范围内
        while (2 * k + 1 <= end) {
            //由于要变化,所以先存储左儿子
            int j = 2 * k + 1;
            //判断右儿子是否在单位内,先左右孩子比较找出较大的
            if (j + 1 <= end && nums[j + 1] > nums[j]) {
                j ++;
            }
            //如果比父节点大,就交换,否则退出
            if (nums[j] > nums[k]) {
                swap(nums, j, k);
            } else {
                break;
            }
            //迭代往下,让当前结点变成儿子结点
            k = j;
        }
    }

    public void swap(int[] nums, int i, int j) {
        int t = nums[i];
        nums[i] = nums[j];
        nums[j] = t;
    }
}
这篇关于Leetcode--Java--912. 排序数组的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!