[解题报告]《算法零基础100讲》(第37讲) 排序进阶 - 快速排序

简介: [解题报告]《算法零基础100讲》(第37讲) 排序进阶 - 快速排序

文章目录

 零、写在前面

 一、主要知识点

           快速排序

 二、课后习题

           539. 最小时间差

           977. 有序数组的平方

           870. 优势洗牌

           881. 救生艇

 写在最后

零、写在前面

今天是打卡的第37天,今天的难度一般般,赶紧写写写篇python爬虫试试水0.0 知识点在:


《算法零基础100讲》(第37讲) 排序进阶 - 快速排序


一、主要知识点

c语言中常见的排序方式


快速排序

基于分治的思想,利用哨兵作为比较的点,将大于哨兵点


void swap(int *a, int *b){//交换节点
    if(a == b) return;  //这是个大坑 如果a和b是同一个元素会变成0
    *a = *a ^ *b;
    *b = *a ^ *b;
    *a = *a ^ *b;
}
int Partition(int *a, int l, int r){
    int i = l + 1, j = l + 1, idx = l + (r - l) /2, pivox = a[idx]; //i 和j用于划分 idx选择中间元素进行分治
    swap(&a[l], &a[idx]);  //将idx暂存到l的位置
    while(i <= r) //进行交换 使j前元素小于idx位置 
        if(a[i++] < pivox)
            swap(&a[i-1],&a[j++]);
    swap(&a[l],&a[j-1]);//将idx元素放回
    return j - 1;//返回idx的位置
}
void QuickSort(int *a,int l,int r){
    if(l < r){
        int mid = Partition(a,l,r);
        QuickSort(a,l,mid - 1);//排序左边
        QuickSort(a,mid + 1,r);//排序右边
    }
}


二、课后习题

539. 最小时间差

539. 最小时间差


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


解题思路


先全部转化为分钟,然后排序,从相邻元素的差值里面选一个最小的就好了,如果跨天的话一定是第一个减最后一个


int cmp(int *a,int*b){
    return *a > *b;
}
int findMinDifference(char ** timePoints, int timePointsSize){
    int hash[timePointsSize],hashSize = 0;
    for(int i = 0;i<timePointsSize;i++)     //转化为分
        hash[hashSize++] = (((timePoints[i][0] -'0') * 10) + timePoints[i][1] - '0') * 60 + (timePoints[i][3] - '0')*10 + timePoints[i][4]; 
    qsort(hash,hashSize,sizeof(int),cmp);//排序
    int min = 24*60+hash[0] - hash[hashSize - 1];//最小值设置为最小-最大 + 一天
    for(int i = 1;i < hashSize;i++)//更新最小值
        if(min>hash[i]-hash[i-1])   min = hash[i] - hash[i-1];
    return min;
}


977. 有序数组的平方

977. 有序数组的平方


给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。


解题思路1


先全部平方,然后排序就好了?应该是英雄哥的本意吧?

void swap(int *a, int *b){
    if(a == b) return;
    *a = *a ^ *b;
    *b = *a ^ *b;
    *a = *a ^ *b;
}
int Partition(int *a, int l, int r){
    int i = l + 1, j = l + 1, idx = l + (r - l) /2, pivox = a[idx];
    swap(&a[l], &a[idx]);
    while(i <= r)
        if(a[i++] < pivox)
            swap(&a[i-1],&a[j++]);
    swap(&a[l],&a[j-1]);
    return j - 1;
}
void QuickSort(int *a,int l,int r){
    if(l < r){
        int mid = Partition(a,l,r);
        QuickSort(a,l,mid - 1);
        QuickSort(a,mid + 1,r);
    }
}
int* sortedSquares(int* nums, int numsSize, int* returnSize){
    int* ans = malloc(sizeof(int) * numsSize);
    for(int i = 0;i < numsSize;i++)//转化为平方
        ans[i] = nums[i] * nums[i];
    *returnSize = numsSize;
    QuickSort(ans,0,numsSize - 1);//快排不解释
    return ans;
}




解题思路2


上面太慢了,其实如果从后往前更新数组,那么最大值一定是最小值的平方或者最大值的平方,搜一遍就出来了。有点归并的意思


int* sortedSquares(int* nums, int numsSize, int* returnSize){
    int* ans = malloc(sizeof(int) * numsSize);
    int l = 0, r = numsSize - 1,ansnum = numsSize;
    *returnSize = numsSize;
    while(ansnum){//当没有插入完
        if(nums[l] < 0) //只有小的小于0 才可能比后面的平方大
            if(-nums[l] > nums[r])  ans[--ansnum] = nums[l] * nums[l],l++;
            else ans[--ansnum] = nums[r] * nums[r],r--;
        else ans[--ansnum] = nums[r] * nums[r],r--;
    }
    return ans;
}

870. 优势洗牌

870. 优势洗牌


给定两个大小相等的数组 A 和 B,A 相对于 B 的优势可以用满足 A[i] > B[i] 的索引 i 的数目来描述。

返回 A 的任意排列,使其相对于 B 的优势最大化。


解题思路


这就是田忌赛马啊,找到一个最小的可以赢的值插入,如果怎么都赢不了,就选一个最小的,保证牺牲最小?


int cmp(int *a,int *b){return *a > *b;}
int* advantageCount(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize){
    qsort(nums1,nums1Size,sizeof(int),cmp);
    int *ans = malloc(sizeof(int) * nums2Size);
    bool hash[nums1Size];//标记元素是否使用
    memset(hash,0,sizeof(hash));
    for(int i = 0;i < nums2Size;i++){
        int low = 0, high = nums1Size;
        while(low < high){//找到最小的元素
            int mid = low + (high - low )/2;
            if(nums1[mid] <= nums2[i])   low = mid + 1;
            else high = mid;
        }
        while(high < nums1Size && hash[high]) //未被使用的最小元素
            high++;
        if(high == nums1Size){//如果没找到就找个最小的
            int k = 0;
            while(hash[k]) k++;
            hash[k] = 1;
            ans[i] = nums1[k];
        }
        else {  //直接将找到的值当作解插入
            hash[high] = 1;
            ans[i] = nums1[high];
        }
    }
    *returnSize = nums2Size;
    return ans;
}

881. 救生艇

881. 救生艇


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

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

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


解题思路


这也是田忌赛马,对于每个比较大的值如果能找到一个较小的值与之同船就一起,没有就自己。


int cmp(int *a,int *b){return *a > *b;}
int numRescueBoats(int* people, int peopleSize, int limit){
    qsort(people,peopleSize,sizeof(int),cmp);
    int low = 0, high = peopleSize - 1,ans = 0;
    while(low <= high){
        if(people[low] + people[high] > limit)  --high;//最小值不能和之一起
        else ++low,--high;//最大最小一起乘船?
        ans++;
    }
    return ans;
}
相关文章
|
2月前
|
搜索推荐 C语言
【排序算法】快速排序升级版--三路快排详解 + 实现(c语言)
本文介绍了快速排序的升级版——三路快排。传统快速排序在处理大量相同元素时效率较低,而三路快排通过将数组分为三部分(小于、等于、大于基准值)来优化这一问题。文章详细讲解了三路快排的实现步骤,并提供了完整的代码示例。
71 4
|
2月前
|
存储 搜索推荐 Python
用 Python 实现快速排序算法。
快速排序的平均时间复杂度为$O(nlogn)$,空间复杂度为$O(logn)$。它在大多数情况下表现良好,但在某些特殊情况下可能会退化为最坏情况,时间复杂度为$O(n^2)$。你可以根据实际需求对代码进行调整和修改,或者尝试使用其他优化策略来提高快速排序的性能
140 61
|
2月前
|
搜索推荐 算法 C语言
【排序算法】八大排序(下)(c语言实现)(附源码)
本文继续学习并实现了八大排序算法中的后四种:堆排序、快速排序、归并排序和计数排序。详细介绍了每种排序算法的原理、步骤和代码实现,并通过测试数据展示了它们的性能表现。堆排序利用堆的特性进行排序,快速排序通过递归和多种划分方法实现高效排序,归并排序通过分治法将问题分解后再合并,计数排序则通过统计每个元素的出现次数实现非比较排序。最后,文章还对比了这些排序算法在处理一百万个整形数据时的运行时间,帮助读者了解不同算法的优劣。
172 7
|
2月前
|
搜索推荐 算法 C语言
【排序算法】八大排序(上)(c语言实现)(附源码)
本文介绍了四种常见的排序算法:冒泡排序、选择排序、插入排序和希尔排序。通过具体的代码实现和测试数据,详细解释了每种算法的工作原理和性能特点。冒泡排序通过不断交换相邻元素来排序,选择排序通过选择最小元素进行交换,插入排序通过逐步插入元素到已排序部分,而希尔排序则是插入排序的改进版,通过预排序使数据更接近有序,从而提高效率。文章最后总结了这四种算法的空间和时间复杂度,以及它们的稳定性。
142 8
|
3月前
|
搜索推荐 Shell
解析排序算法:十大排序方法的工作原理与性能比较
解析排序算法:十大排序方法的工作原理与性能比较
110 9
|
3月前
|
算法 搜索推荐 Shell
数据结构与算法学习十二:希尔排序、快速排序(递归、好理解)、归并排序(递归、难理解)
这篇文章介绍了希尔排序、快速排序和归并排序三种排序算法的基本概念、实现思路、代码实现及其测试结果。
67 1
|
3月前
|
算法 搜索推荐 Java
数据结构与算法学习十三:基数排序,以空间换时间的稳定式排序,速度很快。
基数排序是一种稳定的排序算法,通过将数字按位数切割并分配到不同的桶中,以空间换时间的方式实现快速排序,但占用内存较大,不适合含有负数的数组。
51 0
数据结构与算法学习十三:基数排序,以空间换时间的稳定式排序,速度很快。
|
3月前
|
搜索推荐 Java Go
深入了解快速排序算法
深入了解快速排序算法
82 2
|
3月前
|
算法 Java 程序员
【算法每日一练及解题思路】有n级台阶,一次只能上1级或2级,共有多少种走法?
本文深入解析了“爬楼梯问题”,探讨了递归与迭代两种解法,并提供了Java代码实现。通过分析问题本质,帮助读者理解动态规划技巧,提高解决实际编程问题的能力。关键词:Java, 算法, 动态规划, 爬楼梯问题, 递归, 迭代。
151 0
|
3月前
|
算法
❤️算法笔记❤️-(每日一刷-83、删除排序链表中的重复项)
❤️算法笔记❤️-(每日一刷-83、删除排序链表中的重复项)
41 0