力扣经典题目之912.排序数组(使用希尔排序解决)

今天继续给大家分享一道力扣的做题心得今天这道题目是 912.排序数组

题目链接: 912. 排序数组 - 力扣(LeetCode)

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

你必须在 不使用任何内置函数 的情况下解决问题,时间复杂度为 O(nlog(n)),并且空间复杂度尽可能小。

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


1,题目分析

此题不难,单纯考察排序,这里我们使用希尔排序来完成此题,希尔排序是一种基于插入排序的改进算法,它通过比较距离一定间隔的元素来工作,然后逐步减小间隔,直到间隔为1时,整个数组基本有序,最后使用插入排序完成最终排序。话不多说,直接上解题代码。

2,解题思路

java 复制代码
class Solution {
    public int[] sortArray(int[] a) {
        int len = a.length;
        int gap = len / 2; // 初始间隔

        while (gap > 0) {
            // 对每个子列表进行插入排序
            for (int i = gap; i < len; i++) {
                int j = i;
                int tmp = a[i];
                // 插入排序,将a[i]插入到前面的有序子列表中
                for (j = i; j >= gap && tmp < a[j - gap]; j -= gap) {
                    a[j] = a[j - gap];
                }
                a[j] = tmp;
            }
            gap /= 2; // 减小间隔
        }
        return a;
    }
}

初始化间隔:

  • int gap = len / 2;:初始间隔设置为数组长度的一半。这个间隔用于确定哪些元素将被比较和交换。

外层循环:

  • while (gap > 0):只要间隔大于0,就继续进行排序。每次循环结束时,间隔减半,直到间隔为1。

内层循环:

  • for (int i = gap; i < len; i++):从间隔gap开始遍历数组。每个元素a[i]将被插入到前面的有序子列表中。
  • int j = i;:初始化一个索引j,用于内层的插入排序。
  • int tmp = a[i];:保存当前元素a[i]的值,用于后续的插入操作。

插入排序:

  • for (j = i; j >= gap && tmp < a[j - gap]; j -= gap):从当前元素a[i]开始,向前比较和移动元素,直到找到合适的位置插入tmp。这里的关键是比较tmp和a[j - gap],如果tmp小于a[j - gap],则将a[j - gap]向后移动一个间隔。
  • a[j] = tmp;:将tmp插入到正确的位置。

减小间隔:

  • gap /= 2;:每次外层循环结束时,间隔减半。这使得算法逐步从宏观的调整(大间隔)过渡到微观的调整(小间隔),最终在间隔为1时进行精细的插入排序。

代码难点

理解希尔排序的原理:
  • 希尔排序的关键在于间隔序列的设置。不同的间隔序列会影响算法的性能。在代码中,间隔每次减半,这是一种常见的选择,但不是最优的。例如,可以使用更复杂的间隔序列,如Hibbard序列(1, 3, 7, 15, ...)或Sedgewick序列(1, 5, 19, 41, ...),这些序列可以进一步优化算法的性能。
插入排序的实现:
  • 插入排序部分需要仔细处理索引和条件判断。特别是for (j = i; j >= gap && tmp < a[j - gap]; j -= gap)这个循环,需要确保索引j不会越界,并且正确地将tmp插入到合适的位置。
性能优化:
  • 希尔排序的性能在很大程度上取决于间隔序列的选择。虽然你的实现已经能够正确排序,但通过选择更优的间隔序列,可以进一步提高算法的效率。

总结

实现了希尔排序算法,能够有效地对数组进行排序。通过逐步减小间隔,算法从宏观调整过渡到微观调整,最终使用插入排序完成排序。理解间隔序列的选择和插入排序的实现是掌握希尔排序的关键。通过选择更优的间隔序列,可以进一步优化算法的性能。

4,总结

感谢大家的阅读,希望这篇解题心得能为大家带来一些收获,我们共同进步!大家的点赞就是我的动力谢谢大家,还有什么更优解或者问题欢迎大家在评论区讨论分享!

相关推荐
鶴哥只手遮天几秒前
Spring AI 2.0.1 深度解析-第 02 章 核心抽象层:`Model` / `StreamingModel` 与 ChatModel 体系
java·人工智能·开源
鶴哥只手遮天1 分钟前
Spring AI 2.0.1 深度解析-第 01 章 全景:模块拓扑、依赖层次与设计哲学
java·人工智能·开源
鶴哥只手遮天5 分钟前
Spring AI 2.0.1 深度解析-第 05 章 Advisor 架构:接口体系、栈式链与 context 传播
java·人工智能·开源
鶴哥只手遮天8 分钟前
Spring AI 2.0.1 深度解析-第 04 章 `ChatClient` 全流程:Builder、两条链路与结构化输出
java·人工智能·开源
鶴哥只手遮天8 分钟前
Spring AI 2.0.1 深度解析-第 08 章 RAG 组件逐个拆解:实现细节与八个可投产组件
java·人工智能·开源
SL_staff1 小时前
告别报表重复开发:JVS-BI 模板市场的参数化继承实践
java·数据分析·数据可视化
SL_staff2 小时前
从邮箱传文档到协同流重构:企业文档协作的系统性破局实践
java·开源·github
zyl7654 小时前
FlashAttention 详解:从 GPU 硬件、普通 Attention 到分块计算与 Online Softmax
算法
smallyoung4 小时前
告别N+1:Spring Boot 一键数据翻译框架体系
java·后端·架构
Bazingga6 小时前
Java16 record 完整拆解——语法、语义、限制、反射
java·后端