今天继续给大家分享一道力扣的做题心得今天这道题目是 912.排序数组
题目:给你一个整数数组 nums
,请你将该数组升序排列。
你必须在 不使用任何内置函数 的情况下解决问题,时间复杂度为 O(nlog(n))
,并且空间复杂度尽可能小。
示例 1: 输入:nums = [5,2,3,1] 输出:[1,2,3,5]
1,题目分析
此题不难,单纯考察排序,这里我们使用希尔排序来完成此题,希尔排序是一种基于插入排序的改进算法,它通过比较距离一定间隔的元素来工作,然后逐步减小间隔,直到间隔为1时,整个数组基本有序,最后使用插入排序完成最终排序。话不多说,直接上解题代码。
2,解题思路
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,总结
感谢大家的阅读,希望这篇解题心得能为大家带来一些收获,我们共同进步!大家的点赞就是我的动力谢谢大家,还有什么更优解或者问题欢迎大家在评论区讨论分享!