希尔排序
原理
希尔排序是D.L.Shell在对直接插入排序改进后的算法。
采取跳跃分割的策略: 将相距某个“增量”的记录组成一个子序列,这样才能保证在子序列内分别进行直接插入排序后得到的结果是基本有序而不是局部有序。 即缩小增量。
增量要求:
- 最后的增量一定是 1 。
- 增量尽可能互素。
详细图解可看:希尔排序
习题
912. 排序数组
原题链接:912. 排序数组
希尔排序代码
首先看这个题,居然是个中等题。就写个排序还中等题,所以要考虑时间复杂度。
static void Shell_Sort(int* nums, int numsSize, int gap);
int* sortArray(int* nums, int numsSize, int* returnSize)
{
if (nums == NULL || numsSize <= 0)
return NULL;
int gap[3] = {5, 3, 1};
for (int i = 0; i < 3; ++i)
{
Shell_Sort(nums, numsSize, gap[i]);
}
*returnSize = numsSize;
return nums;
}
static void Shell_Sort(int* nums, int numsSize, int gap)
{
int tmp = 0;
int i = 0, j = 0;
for (i = gap; i < numsSize; i += gap)
{
tmp = nums[i];
for (j = i - gap; j >= 0; j -= gap)
{
if (tmp < nums[j])
{
nums[j + gap] = nums[j];
}
else
{
break;
}
}
nums[j + gap] = tmp;
}
}
这个排序会将传统排序的时间复杂度O(n ^ 2)降低至 O(n ^ 1.3 ~ 1.5), 但还是不能做出题。
来看看结果:
凡是O(n ^ 2)的都过不了。。。
905. 按奇偶排序数组
原题链接:905. 按奇偶排序数组
代码
首尾双指针
如果当前首尾指针满足题意就直接跳过
class Solution {
public:
void Swap(int* a, int* b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
vector<int> sortArrayByParity(vector<int>& nums)
{
int left = 0, right = nums.size() - 1;
while (left < right)
{
if ((nums[left] & 1) == 0)
{
left++;
continue;
}
if ((nums[right] & 1) == 1)
{
right--;
continue;
}
Swap(&nums[left], &nums[right]);
}
return nums;
}
};
976. 三角形的最大周长
原题链接:976. 三角形的最大周长
解析
要满足是三角形且周长最大,那找出最大的三条边,如果最大的边没有其他两条边大,就合理,那可以直接返回了。
按照从大到小排序,即可找到最大的边。
class Solution {
public:
int largestPerimeter(vector<int>& nums)
{
int n = nums.size();
if (n <= 2)
return 0;
sort(nums.begin(), nums.end(), greater<int>());
for (int i = 0; i < n - 2; ++i)
{
if (nums[i] < nums[i + 1] + nums[i + 2])
{
return nums[i] + nums[i + 1] + nums[i + 2];
}
}
return 0;
}
};
练习题
这些题目前面章节都做过,可以复习。
难度 | 题目 |
---|---|
简单 | 169. 多数元素 |
简单 | 217. 存在重复元素 |
困难 | 164. 最大间距 |
end
原文链接:《算法零基础100讲》(第38讲) 排序进阶 - 希尔排序
作者:英雄哪里出来