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;
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值