【题解】《算法零基础100讲》(第38讲) 排序进阶 - 希尔排序

希尔排序

直接插入排序和希尔排序

原理

希尔排序是D.L.Shell在对直接插入排序改进后的算法。

采取跳跃分割的策略: 将相距某个“增量”的记录组成一个子序列,这样才能保证在子序列内分别进行直接插入排序后得到的结果是基本有序而不是局部有序。 即缩小增量。

增量要求:

  1. 最后的增量一定是 1 。
  2. 增量尽可能互素。

详细图解可看:希尔排序

习题

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讲) 排序进阶 - 希尔排序

作者:英雄哪里出来

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_索伦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值