[解题报告]《算法零基础100讲》(第36讲) 排序进阶 - 归并排序

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

文章目录

零、写在前面

一、主要知识点

         归并排序

二、课后习题

        164. 最大间距

        912. 排序数组

        217. 存在重复元素

        169. 多数元素

        面试题 10.01. 合并排序的数组

       148. 排序链表

写在最后

零、写在前面

今天是打卡的第36天,今天的难度一般般,赶紧写写复习考试了-.-知识点在:


《算法零基础100讲》(第36讲) 排序进阶 - 归并排序


一、主要知识点

c语言中常见的排序方式


归并排序

划分中间位置为分割点,对分割后的元素进行排序,其中利用了选择排序的相对有序情况下时间复杂度较低的特性。


int a[maxn];
void MergeSort(int *nums, int l, int r) {
    int i, mid, p, lp, rp;
    int *tmp = (int *)malloc( (r-l+1) * sizeof(int) );    //辅助数组 
    if(l >= r) {
        return ;                                          //只有一个元素
    }
    mid = (l + r) >> 1;                                   // 划分
    MergeSort(nums, l, mid);                              // 排序右边
    MergeSort(nums, mid+1, r);                            // 排序左边
    p = 0;                                                // 辅助数组指针
    lp = l, rp = mid+1;                                   // 指向左右两边的元素
    while(lp <= mid || rp <= r) {                         // 双指针判断
        if(lp > mid) {
            tmp[p++] = nums[rp++];                        // 左部分插入完了
        }else if(rp > r) {
            tmp[p++] = nums[lp++];                        // 右部分插入结束
        }else {
            if(nums[lp] <= nums[rp]) {                    // 选择较小的插入
                tmp[p++] = nums[lp++];
            }else {
                tmp[p++] = nums[rp++];
            }
        }
    }
    for(i = 0; i < r-l+1; ++i) {
         nums[l+i] = tmp[i];                            // 写回
    } 
    free(tmp);                                            // 释放空间
}

二、课后习题

164. 最大间距

164. 最大间距


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

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


解题思路


先排序然后用max记录最大值 返回就好了?


int cmp(int *a, int *b){return *b < *a;}//排序数组
int maximumGap(int* nums, int numsSize){
    qsort(nums ,numsSize ,sizeof(int) ,cmp);//排序
    int max = 0;  //判断
    for(int i = 1;i < numsSize;i++)
        if(max < nums[i] - nums[i - 1]) max = nums[i] - nums[i - 1];//更新值
    return max;
}

912. 排序数组

912. 排序数组


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


解题思路


直接排序就好了


int cmp(const void *a,const void *b){
    return *(int *)a - *(int *)b;
}
int* sortArray(int* nums, int numsSize, int* returnSize){
    qsort(nums,numsSize,sizeof(int),cmp);//排序
    *returnSize = numsSize;//返回
    return nums;
}


217. 存在重复元素

217. 存在重复元素


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

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


解题思路


直接排序就好了,如果两个元素相同就返回false


int cmp(int *a,int *b){
    return *a > *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;
}


169. 多数元素

169. 多数元素


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

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


解题思路


这个其实很有意思,假如 我用一个出现最多的元素和其它元素相消除,那么由于最多的元素是大于一半 的,最后剩下的一定是最多的元素。 基于这种思想我就可以写出来下面的代码。


int majorityElement(int* nums, int numsSize){
    int maxnum = 0,maxtime = 0;
    for(int i = 0;i < numsSize;i++){
        if(maxtime == 0){ //选择此元素为最多元素
            maxnum = nums[i];
            maxtime++;
        }
        else if(nums[i] == maxnum) maxtime++;//增加计数
        else maxtime--;   //减少计数
    }
    return maxnum;
}


面试题 10.01. 合并排序的数组

面试题 10.01. 合并排序的数组


给定两个排序后的数组 A 和 B,其中 A 的末端有足够的缓冲空间容纳 B。 编写一个方法,将 B 合并入 A 并排序。

初始化 A 和 B 的元素数量分别为 m 和 n。


解题思路


这个如果采用辅助元素啥的,都是浪费空间,最简单的就是从后往前进行二路归并排序。这样不会产生覆盖问题。


void merge(int* A, int ASize, int m, int* B, int BSize, int n){
    int k = m + n -1, low = m - 1,high = n - 1; //k为最终数组指针
    while(low != -1|| high != -1){//A或B还有元素
        if(low != -1 && high != -1) //A和B都有元素
            if(A[low] < B[high])  A[k--] = B[high--];
            else                A[k--] = A[low --];
        else if(low != -1)  A[k--] = A[low--];  //将所有B插入
        else        A[k--] = B[high--];   //将所有A插入
    }
}


148. 排序链表

148. 排序链表


给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。


解题思路


我用一个数组把所有的节点存进去,然后排序,然后再链接起来0.0


bool sort(const struct ListNode **a,const struct ListNode **b){
    struct ListNode *p = *a, *q = *b;
    return p->val > q->val;
}
struct ListNode* sortList(struct ListNode* head){
    if(!head) return head;
    struct ListNode *a[50001];
    int len = 0;
    while(head){  //插入表中
        a[len++] = head;
        head = head->next;
    }
    qsort(a,len,sizeof(struct ListNode* ),sort);//对表内元素按照val大小排序
    for(int i = 0;i<len - 1;++i){ //链接起来
        a[i]->next =a[i+1];
        //printf("%d",a[i]->val);
    }
    a[len -1]->next = 0;  //最后的NULL
    return a[0];  //返回第一个元素
}


相关文章
|
2月前
|
搜索推荐 算法 C语言
【排序算法】八大排序(下)(c语言实现)(附源码)
本文继续学习并实现了八大排序算法中的后四种:堆排序、快速排序、归并排序和计数排序。详细介绍了每种排序算法的原理、步骤和代码实现,并通过测试数据展示了它们的性能表现。堆排序利用堆的特性进行排序,快速排序通过递归和多种划分方法实现高效排序,归并排序通过分治法将问题分解后再合并,计数排序则通过统计每个元素的出现次数实现非比较排序。最后,文章还对比了这些排序算法在处理一百万个整形数据时的运行时间,帮助读者了解不同算法的优劣。
172 7
|
2月前
|
搜索推荐 算法 C语言
【排序算法】八大排序(上)(c语言实现)(附源码)
本文介绍了四种常见的排序算法:冒泡排序、选择排序、插入排序和希尔排序。通过具体的代码实现和测试数据,详细解释了每种算法的工作原理和性能特点。冒泡排序通过不断交换相邻元素来排序,选择排序通过选择最小元素进行交换,插入排序通过逐步插入元素到已排序部分,而希尔排序则是插入排序的改进版,通过预排序使数据更接近有序,从而提高效率。文章最后总结了这四种算法的空间和时间复杂度,以及它们的稳定性。
142 8
|
3月前
|
搜索推荐 Shell
解析排序算法:十大排序方法的工作原理与性能比较
解析排序算法:十大排序方法的工作原理与性能比较
110 9
|
3月前
|
算法 搜索推荐 Shell
数据结构与算法学习十二:希尔排序、快速排序(递归、好理解)、归并排序(递归、难理解)
这篇文章介绍了希尔排序、快速排序和归并排序三种排序算法的基本概念、实现思路、代码实现及其测试结果。
67 1
|
3月前
|
算法 搜索推荐 Java
数据结构与算法学习十三:基数排序,以空间换时间的稳定式排序,速度很快。
基数排序是一种稳定的排序算法,通过将数字按位数切割并分配到不同的桶中,以空间换时间的方式实现快速排序,但占用内存较大,不适合含有负数的数组。
51 0
数据结构与算法学习十三:基数排序,以空间换时间的稳定式排序,速度很快。
|
3月前
|
算法 Java 程序员
【算法每日一练及解题思路】有n级台阶,一次只能上1级或2级,共有多少种走法?
本文深入解析了“爬楼梯问题”,探讨了递归与迭代两种解法,并提供了Java代码实现。通过分析问题本质,帮助读者理解动态规划技巧,提高解决实际编程问题的能力。关键词:Java, 算法, 动态规划, 爬楼梯问题, 递归, 迭代。
151 0
|
3月前
|
算法
❤️算法笔记❤️-(每日一刷-83、删除排序链表中的重复项)
❤️算法笔记❤️-(每日一刷-83、删除排序链表中的重复项)
41 0
|
3月前
|
存储 搜索推荐 算法
【排序算法(二)】——冒泡排序、快速排序和归并排序—>深层解析
【排序算法(二)】——冒泡排序、快速排序和归并排序—>深层解析
|
3月前
|
存储 算法 搜索推荐
算法进阶之路:Python 归并排序深度剖析,让数据排序变得艺术起来!
算法进阶之路:Python 归并排序深度剖析,让数据排序变得艺术起来!
92 0
|
3月前
|
算法 C++
【算法解题思想】动态规划+深度优先搜索(C/C++)
【算法解题思想】动态规划+深度优先搜索(C/C++)