【解题笔记】排序

本文介绍了六个实用的算法问题:排序数组、寻找多数元素、检测重复、最大间距、按奇偶排序和最小时间差,展示了如何通过qsort排序函数实现高效解决。还涉及三角形最大周长和救生艇问题,展示在实际场景中的应用。
摘要由CSDN通过智能技术生成

1.排序数组

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

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
 int cmp(const void *a, const void *b){
     return *(int *)a - *(int *)b;
 }
//若a>b,则返回值大于0,a在b的右边  大的在右边
//若a<b,则返回值小于0,a在b的左边  大的在右边
//若a=b,则返回值等于0,a和b的位置不确定
//该比较函数是按升序进行排列
int* sortArray(int* nums, int numsSize, int* returnSize){
    qsort(nums, numsSize, sizeof(int), cmp);
    *returnSize = numsSize;
    return nums;
}
//qsort 是排序函数;
//函数原型:
void qsort(void *base, size_t nitems, size_t size, int (*compar)(const void *, const               void*)         
//base : 指向要排序数组的第一个元素的指针
//nitems:由base指向的数组元素的大小
//size :每个元素的大小,以字节为单位
//compar:函数指针,用来比较两个元素的函数,决定元素的排列方式
//若函数返回小于0,则第一个在第二个之前
//若函数返回大于0,则第一个在第二个之后
//若函数返回等于0,则第一个和第二个不确定

2.多数元素

给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。你可以假设数组是非空的,并且给定的数组总是存在多数元素。

int cmp(const void *a, const void *b){
    return *(int *)a - *(int *)b;
}
int majorityElement(int* nums, int numsSize){
    qsort(nums, numsSize, sizeof(int), cmp);
    return nums[numsSize / 2];
}
//多数元素就是这个元素在数组的数量大于一半
//将数组的元素排序后,多数元素占一半以上,所以处于中间的位置的元素一定是多数元素

3.存在重复元素

给定一个整数数组,判断是否存在重复元素。如果存在一值在数组中出现至少两次,函数返回 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 = 1; i < numsSize; i++){
        if(nums[i] == nums[i - 1])
            return true;
    }
    return false;
}
//先将元素进行排序
//若相邻的元素相等,则存在。
//若所有的相邻元素不存在,则不存在

4.最大间距

给定一个无序的数组,找出数组在排序之后,相邻元素之间最大的差值。如果数组元素个数小于 2,则返回 0

int cmp(void const *a, void const *b){
    return *(int *)a -*(int *)b;
}
int maximumGap(int* nums, int numsSize){
    int max = 0;
    qsort(nums, numsSize, sizeof(int), cmp);
    for(int i = 1; i < numsSize; i++){
        int ret = nums[i] - nums[i -1];
        if(ret > max)
            max = ret;
    }
    return max;
}
//令最大为max = 0,将数组排序后,比较相邻两个数的大小的绝对值,若比max大,则那个值赋给max
//若元素是1个,则下标为0,不会进入循坏,返回0

5.按奇偶排序数组

给定一个非负整数数组 A,返回一个数组,在该数组中, A 的所有偶数元素之后跟着所有奇数元素。你可以返回满足此条件的任何数组作为答案。

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int Qua(int x){
    return x % 2;
}
int cmp(const void *a, const void *b){
    return Qua(*(int *)a) - Qua(*(int *)b);
}
int* sortArrayByParity(int* nums, int numsSize, int* returnSize){
    qsort(nums, numsSize, sizeof(int), cmp);
    *returnSize = numsSize;
    return nums;
}
//设置一个比较函数,将偶数放在前面,奇数放在后面
//偶数模2是0,奇数模2是1,偶数的值比奇数的小,
//若a是偶数,b是奇数,返回-1,a在b的左边
//若a是奇数,b是偶数,返回+1,a在b的右边
//前面为偶数,后面为奇数

6.最小时间差

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

int cmp(const void *a, const void *b){
    return *(int *)a - *(int *)b;
}
int findMinDifference(char ** timePoints, int timePointsSize){
    int min = 1440;
    int a, b;
    int * ret = (int *)malloc(timePointsSize * sizeof(int));
    for(int i = 0; i < timePointsSize; i++){
        sscanf(timePoints[i], "%d:%d", &a, &b);
        ret[i] = a * 60 + b;
    }
    qsort(ret, timePointsSize, sizeof(int), cmp);
    for(int i = 1; i < timePointsSize; i++){
        if((ret[i] - ret[i - 1]) < min){
            min = ret[i] - ret[i - 1] ;
        }
    }
    if((ret[0] - ret[timePointsSize - 1] + 1440) < min)
        min = ret[0] - ret[timePointsSize - 1] + 1440;
    return min;
}
//求相邻时间的最小时间差
//先将时间转换成分钟,然后相邻两个之间减,比最小值,第一个时间和最后一个时间也是相邻的
//计算这两个时间的分钟,最小值减最大值+1440(24小时)
//sscanf函数是从第一个参数的文件中读取数据,按照第二个参数的格式进行转换,将转换后的数据存在后面的参数中

7.三角形最大周长

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

int cmp(const void *a, const void *b){
    return *(int *)a - *(int *)b;
}
int largestPerimeter(int* nums, int numsSize){
    qsort(nums, numsSize, sizeof(int), cmp);
    for(int i = numsSize - 1; i >= 2; i--){
        if(nums[i - 1] + nums[i - 2] > nums[i]){
            return nums[i - 1] + nums[i - 2] + nums[i];
        }
    }
    return 0;
}
//先将所有的元素从小到大排序,若最大的一个值小于两个较小的值的和,则能构成三角形,此时为最大的周长
//若不大于,则将三个元素向小的方向移动一个位置,
//若全部走遍后,任然没有,则不能构成三角形

8.救生艇

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

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

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

int cmp(const void *a, const void *b){
    return *(int *)a - *(int *)b;
}
int numRescueBoats(int* people, int peopleSize, int limit){
    qsort(people, peopleSize, sizeof(int), cmp);
    int l = 0, r = peopleSize - 1, count = 0;
    while(l <= r){
        if(l == r){
            count++;
            l++;
        }
        else if (people[l] + people[r] > limit){
            count++;
            r--;
        }
        else {
            count++;
            r--;
            l++;
        }
    }
    return count;
}
//先将人的体重按从小到大排列
//若最大的那个人的体重比最大承重量大,则船的个数加1,将目标向前移动
//若最大的那个人的体重与最小的人的体重之和大于承重量,则船的个数加1,后面的目标向前移动一
//若最大的那个人的体重与最小的人的体重之和小于称重量,船的个数加1,后面的目标向前移动一位,前面的目标向后移动一位
//若只剩下一个人之后,船加一,
//l是体重最小的,r是体重的最大,当体重最小的小于等于最大的时,还有人未上船,当体重最小大于体重最大时,人全部上完。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值