《LeetCode零基础指南》(第六讲) C排序API

本文通过讲解八个算法问题,如排序数组、多数元素查找、重复元素检测等,展示了如何利用C语言内置函数qsort进行高效排序并解决相关问题。涉及的算法包括冒泡排序、快速排序、贪心算法等,适合学习者理解排序在实际问题中的应用。
摘要由CSDN通过智能技术生成

1. 排序数组

912. 排序数组

  • 题目

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

  • 题目分析
  • 直接使用c语言的内置函数qsort就可以完成该题
  • 源码实现
/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int *cmp(int *a, int *b)
{
    return *a - *b;
}
int* sortArray(int* nums, int numsSize, int* returnSize){
    qsort(nums, numsSize, sizeof(int), cmp);
    *returnSize = numsSize;
    return nums;
}

2. 多数元素

169. 多数元素

  • 题目

给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。

你可以假设数组是非空的,并且给定的数组总是存在多数元素。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/majority-element
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

  • 题目分析

根据题目的定义可以推导出,只需要找到n/2的位置中的元素,由于给定的数组元素是无序的,所以在找之前需要对其排序,排序完成后直接返回n/2位置的元素

  • 源码实现
int cmp(int *a, int *b)
{
    return *a - *b;
}

int majorityElement(int* nums, int numsSize){
    qsort(nums, numsSize, sizeof(int), cmp);
    return nums[numsSize / 2];
}

3.存在重复元素

17. 存在重复元素

  • 题目

给定一个整数数组,判断是否存在重复元素。

如果存在一值在数组中出现至少两次,函数返回 true 。如果数组中每个元素都不相同,则返回 false

  • 题目分析

重复元素意味着至少存在两个元素,对其进行排序后,我们就只需要比较当前元素与相邻元素即可

  • 源码实现
int cmp(const void* a, const void* b) {
   return *(int *)a - *(int *)b;
}
//先排序后比较
bool containsDuplicate(int* nums, int numsSize) {
    qsort(nums, numsSize, sizeof(int), cmp);
    for (int i = 0; i < numsSize - 1; i++) {
        if (nums[i] == nums[i + 1]) {
            return true;
        }
    }
    return false;
}

4. 最大间距

164. 最大间距

  • 题目

给定一个无序的数组,找出数组在排序之后,相邻元素之间最大的差值。

如果数组元素个数小于 2,则返回 0。

  • 思路分析

要想找最大的间距,就需要找到较大的数与较小的相邻数,在无序的数组中这是比较难操作的,对其进行排序后就能简化操作,这样就只需要相邻元素两两相减,更新最大间距即可

  • 源码实现
int cmp(const void* a, const void* b)
{
    return *(int *)a - *(int *)b;
}

int maximumGap(int* nums, int numsSize){
    if(numsSize < 2)	//数组元素个数小于2直接返回0
    {
        return 0;
    }
    qsort(nums, numsSize, sizeof(int), cmp);

    int i;
    int max_num = 0;
    int num;
    for(i = 0; i < numsSize - 1; ++i)
    {
        num = nums[i + 1] - nums[i];	//比较相邻元素的差值
        max_num = num > max_num ? num:max_num;	//保存最大间距
    }
    
    return max_num;
}

5. 按奇偶排序数组

905. 按奇偶排序数组

  • 题目

给定一个非负整数数组 A,返回一个数组,在该数组中, A 的所有偶数元素之后跟着所有奇数元素。

你可以返回满足此条件的任何数组作为答案。

  • 题目分析

这道题有多种思路,这里我使用的内置函数qsort实现按奇偶排序。

数组元素为奇数时将元素向右移,为偶数时数组元素向左移。利用&运算,为奇数时回调函数返回值大于0,向右移动,反之向左移动。

  • 源码实现
/**
 * Note: The returned array must be malloced, assume caller calls free().
 */

int Qua(int a)
{
    return (a & 1); //奇数时为1,偶数时为0
}

int cmp(const void *a, const void* b)
{
    return Qua(*(int *)a) - Qua(*(int *)b); //为奇数时,大于0,往右排
}

int* sortArrayByParity(int* nums, int numsSize, int* returnSize){
    int *ans = (int *)malloc(sizeof(int) * numsSize);
    //改变数组中元素或元素位置,一般没特殊要求建议创建新数组。
    int i;
    for(i = 0; i < numsSize; ++i)
    {
        ans[i] = nums[i];
    }
    qsort(ans, numsSize, sizeof(int), cmp);
    *returnSize = numsSize;
    return ans;
}

6. 最小时间差

539. 最小时间差

  • 题目

给定一个 24 小时制(小时:分钟 “HH:MM”)的时间列表,找出列表中任意两个时间的最小时间差并以分钟数表示。

  • 题目分析

思路:先将字符串转成对应的整数,排序之后比较数组元素中的差值,保存最小的时间差,最后的结果要注意时间循环(类比12进制的时钟)。

  • 题目给出的是字符串数组,找最小时间差就需要先将字符串转成对应的整数,使用sscanf函数实现
  • 转成整数后全部换算成分钟进行比较
  • 将分钟进行排序,然后找两者之间最小差值
  • 最后注意时间循环,如果不注意,就会出现23:59 00:00之间的差值为1439,实际上结果是1。
  • 源码实现
int cmp(const void *a, const void *b)
{
    return *(int *)a - *(int *)b;
}
int findMinDifference(char ** timePoints, int timePointsSize){
    //1.首先将字符串转成整数
    //2.将整数转换成分钟
    //3.将分钟进行排序处理
    //4.找出相邻间隔之间的最小值
    //5.注意时间的循环

    int *ans = (int *)malloc(sizeof(int) * timePointsSize);

    int i;
    int a, b;
    for(i = 0; i < timePointsSize; ++i)
    {
        sscanf(timePoints[i], "%d:%d", &a, &b);
        ans[i] = a * 60 + b; 
    }

    qsort(ans, timePointsSize, sizeof(int), cmp);
    int min = 1440; //要保证最小的时间差,就初始化为时间的最大值
    for(i = 1; i < timePointsSize; ++i)
    {
        min = fmin(min, ans[i] - ans[i - 1]);
    }

    min = fmin(min , ans[0] - ans[timePointsSize - 1] + 1440); //24小时为一循环
    return min;
}

7. 三角形的最大周长

976. 三角形的最大周长

  • 题目

给定由一些正数(代表长度)组成的数组 A,返回由其中三个长度组成的、面积不为零的三角形的最大周长。

如果不能形成任何面积不为零的三角形,返回 0

  • 题目分析

利用贪心算法思想,要想得到最大的周长的值,只需要判断该数组中最大的三个元素是否构成三角形。

  • 构成三角形的条件:任意两边之和大于第三边。三个元素任意两个组合相加判断是否大于第三边固然是可以的,但是操作复杂且时间复杂度高,不建议使用。
  • 像这种情况我们可以先进行排序,排序之后我们发现a < b < c已经得出两个结论b + c > aa + c < b,现在只需要比较a + b > c
  • 最后求最大周长的值
  • 源码实现
int cmp(const void* a, const void *b)
{
    return *(int *)a - *(int *)b; 
}

int largestPerimeter(int* nums, int numsSize){
    if(numsSize < 2)	//两个元素是无法构成三角形的
    {
        return 0;
    }

    qsort(nums, numsSize, sizeof(int), cmp);
    int i;
	//从最后的元素开始遍历,只要能构成三角形,那么结果就为最大周长
    for(i = numsSize - 1; i >= 2; --i)
    {
        if(nums[i - 2] + nums[i - 1] > nums[i])
        {
            return nums[i - 2] + nums[i - 1] + nums[i];
        }
    }
    return 0;
}

8. 救生艇

881. 救生艇

  • 题目

第 i 个人的体重为 people[i],每艘船可以承载的最大重量为 limit

每艘船最多可同时载两人,但条件是这些人的重量之和最多为 limit

返回载到每一个人所需的最小船数。(保证每个人都能被船载)。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/boats-to-save-people
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

  • 题目分析

要求所需最小船数,就必须保证每次乘坐的是能乘坐的最大值。这种情况使用排序就比较方便对其进行求解。

  • 第一步,排序
  • 第二步,判断最大的体重和最小体重能否一起乘坐一艘船,能就一起走,不能就先让体重大的人先走
  • 第三步,返回结果
  • 源码实现
int cmp(const void* a, const void *b)
{
    return *(int *)a - *(int *)b;
}
int numRescueBoats(int* people, int peopleSize, int limit){
    //体重people[i] , 船能承载的最大体重是limit
    //同时载两人
    //求载到每一个人所需的最小船数
    qsort(people, peopleSize, sizeof(int), cmp);

    int ans = 0;	//统计船的数量
    int left = 0;
    int right = peopleSize - 1;

    while(left <= right)
    {
        if(left == right)	//只有一个人了,直接走
        {
            ++ans;
            break;
        }
        else if(people[left] + people[right] > limit) //最小的与最大的比较,如果大于就让最大的先走
        {
            ++ans;
            right--;
        }
        else
        {
            ++ans;
            right--;
            left++;
        }
    } 
    return ans;
}

总结

以上的所有的题目均参考博主英雄哪里出来的文章,此次最大的收获就是对排序算法的使用,并了解了C语言内置函数qsort函数的使用方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值