ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[学习报告]《LeetCode零基础指南》(第四讲) 指针

2022-03-18 19:32:17  阅读:246  来源: 互联网

标签:指南 return nums int void const cmp LeetCode 指针


学习内容:https://blog.csdn.net/WhereIsHeroFrom/article/details/120875926

一、今日知识点总结

实现简单,时间效率低:冒泡、选择、插入排序
实现相对复杂,效率较高的:归并、快排、希尔排序 等
非比较排序:基数排序、计数排序、桶排序

C语言排序API:qsort

void qsort(void *base, size_t nitems, size_t size, int (*compar)(const void *, const void*));
参数说明
base要排序的数组的第一个元素的指针
nitems数组的个数
size数组元素的大小(数组数据类型的字节大小)
compar用来比较两个元素大小的函数,即函数指针(比较算法的回调函数)

qsort的使用范式

//排序回调函数:用于表示比较的两个数谁在前谁在后的规则
int cmp(const void *a, const void *b){
    return (*(int *)a) - (*(int *)b);//升序排列
    //or 
    return (*(int *)b) - (*(int *)a);//降序排列
}

//...

int a[7] = {0,2,4,1,2,6,1};
qsort(a,7,sizeof(int),cmp);

//...

奇偶排序

int qua(int x){
    return x & 1;//(1) 当奇数,返回1,偶数返回0 
}

int cmp(const void *a, const void *b){
      return qua(*(int *)a) - qua(*(int *)b); //(2) 实现了偶数排前面,奇数排后面
}

为何是偶数排前面,奇数排后面?
qua(x)判断结果是,奇数返回1,偶数返回0;(2)这行表达式实现的是升序排列
代表偶数的0小于代表奇数的1,所以偶数排前面,奇数排后面

关键思想是,根据实际题目需要,根据数据的特点,对排序的元素进行一个转换计算,进而改变排序的规则

二、今日解题

战绩:

image-20220318192549995

912. 排序数组

int cmp(const void *p1,const void*p2){
    return *(int *)p1 - *(int *)p2; //(1) 比较函数
}

int* sortArray(int* nums, int numsSize, int* returnSize){

    qsort(nums,numsSize,sizeof(int),cmp);//(2)调用排序API
  
    *returnSize = numsSize;//(3)告诉调用者排序后的元素个数
    return nums;//(4)返回排序后的数组首地址
}

169. 多数元素

int cmp(const void *p1,const void *p2){
    return *(int *)p1 - *(int *)p2; //比较函数,升序排列
}

int majorityElement(int* nums, int numsSize){

    qsort(nums,numsSize,sizeof(int),cmp);//调用排序函数,得到升序排列后的nums

    return nums[numsSize/2];//题意全部数组都满足存在多数元素(个数超过一半,也就是>n/2),无论这个多数元素是大还是小,[n/2]肯定是他

}

217. 存在重复元素

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;


}

164. 最大间距

int cmp(const void *a,const void *b){
    return *(int *)a - *(int *)b;//升序
}

int maximumGap(int* nums, int numsSize){

    if(numsSize<2){
        return 0;
    }

    qsort(nums,numsSize,sizeof(int),cmp);//升序排序

    int max = 0;//最大值,若后续最大值比max大,max就等于新的最大值
    for(int i = 1;i<numsSize;i++){//后一个减前一个,所有i从1开始
        if(nums[i]-nums[i-1]>max){//相邻元素相减,因为升序排列,故[i]-[i-1]
            max = nums[i]-nums[i-1];//替换最大值
        }
    }
    return max;

}

905. 按奇偶排序数组***

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */

int odd(int num){
    return num&1;//根据奇数二进制最后一位必定为1,偶数为0;位于1后,奇数返回1,偶数返回0;
}

int cmp(const void *a,const void *b){
    return odd(*(int *)a) - odd(*(int *)b);//升序排列,所以偶数排在前面,奇数排在后面
}



int* sortArrayByParity(int* nums, int numsSize, int* returnSize){

    int *ans = (int *)malloc(sizeof(int)*numsSize);//申请一段长度为numSize个int的内存空间,首地址赋值给ans
    for(int i = 0;i<numsSize;i++){
        ans[i] = nums[i];//复制数组元素
    }

    *returnSize = numsSize;//告诉调用者返回的新数组的元素个数
    qsort(ans,numsSize,sizeof(int),cmp);//执行排序
    return ans;

}

539. 最小时间差

int cmp(const void *a,const void *b){
    return *(int *)a - *(int *)b;//升序排列 -- 把时间按照最小到最大排序
  	//因为相邻的时间点的时间差肯定最小(贪心)
}

int findMinDifference(char ** timePoints, int timePointsSize){

    int *times = (int *)malloc(sizeof(int)*timePointsSize);//申请了一个长度为sizeof(int)*timePointsSize的内存空间,首地址赋值给times
    int i,h,m = 0,min = 1440;//24小时的最大时间差为1440分钟,从0点到24点(一天有1440分钟)
    for(i = 0;i<timePointsSize;i++){
        sscanf(timePoints[i],"%d:%d",&h,&m);//通过sscanf把反格式化时间字符串得到小时和分钟
        times[i] = h*60 + m;//计算分钟数,以分钟表示
    }

    qsort(times,timePointsSize,sizeof(int),cmp);//排序

    for(i = 1;i<timePointsSize;i++){//思路和最大间距类似,只是换成了「比小」
        if(times[i] - times[i-1]<min){
            min = times[i] - times[i-1];
        }
    }

    if((times[0] + 1440 - times[timePointsSize-1])<min){//要特别留意的地方:根据上面的计算方式,会漏掉首位和末位这两个时间的比较,最小值和最大值也是相邻的,它们之间是存在时间差最小的可能的情况 ==> 最小时间是排在最大时间之后,例如最大时间是11:55,最小时间是00:01,时间差为6分钟 
        min = times[0] + 1440 - times[timePointsSize-1];//如何理解加1440,从计时器的角度,可以设定每个时间都是从00:00开始计时,而00:01可能是已经走完了24小时并走了1分钟,故加 1440即为00:01的计时
    }

    return min;


}

976. 三角形的最大周长

// 贪心
// a+b>c
// 周长最大 只要c最大,a+b也就最大,没必要全部都相互组合检查一下

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-2]+nums[i-1]>nums[i]){//若该线的前面两条线满足三角形 a+b>c,则该三角形周长一定最大
            return nums[i] + nums[i-1] + nums[i-2];
        }
    }
    return 0;


}

881. 救生艇

以下两个解法就只是在循环结束条件的选用不同

//一次最多两人
//两人重量小于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,cnt = 0;
    while(peopleSize>0){
        
        if(people[l] + people[r] <= limit){
            l++;
            r--;
            peopleSize -=2;
        }else{
            r--;
            peopleSize--;
        }
        cnt++;
    }

    return cnt;

}

//最好就是一次两人,但如何最高效率呢,就是刚好能匹配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);
    //次数people按照升序排列了

    //先让最重的和最轻组合比较,让重的先走,能稍上轻的就稍上轻的,这样船只的承重能力最不浪费
    //且剩余的能组合成功的概率会更大
    //双指针?
    int l=0,r=peopleSize-1;
    int cnt = 0;
    while(l<=r){
        if((people[r] + people[l])<=limit){
            l++;r--;
        }else{
            r--;
        }
        cnt++;
    }
    
    return cnt;
}

三、今日收获

四、今日疑问

五、其他参考

标签:指南,return,nums,int,void,const,cmp,LeetCode,指针
来源: https://blog.csdn.net/campchan/article/details/123582674

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有