前言
今日是五日集训的第三天,今日的训练内容是——排序。
解题报告
1.力扣977
原题链接
https://leetcode-cn.com/problems/squares-of-a-sorted-array/
题目概述
给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
解题思路
这题比较简单,直接构造新的数组把原数组元素平方后放入,随后再利用库函数qsort()
排序后返回即可。
源码剖析
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int cmp(const void*a,const void*b){
return *(int*)a-*(int*)b;
}
int* sortedSquares(int* nums, int numsSize, int* returnSize){
int *ret=(int*)malloc(sizeof(int)*numsSize);
int i;
for(i=0;i<numsSize;++i){
ret[i]=nums[i]*nums[i];
}
qsort(ret,numsSize,sizeof(int),cmp);
*returnSize = numsSize;
return ret;
}
时间复杂度
本题使用了qsort()
进行排序,时间复杂度是O(nlogn)
。
2.力扣268
原题链接
https://leetcode-cn.com/problems/missing-number/
题目概述
给定一个包含 [0, n] 中 n 个数的数组 nums ,找出 [0, n] 这个范围内没有出现在数组中的那个数。
解题思路
只要将原来的数组进行排序,然后用后一项减去前一项,如果相差 2 则说明这两个数字之间缺少了一个数字,直接返回这个数字就可以了。如果这个数字是第一个数,那它就是 0 ,初始化返回的数就是 0 ,直接返回即可。如果它是最后一个数,那单独提出来这个情况进行返回就可以啦。
源码剖析
int cmp(const void*a,const void*b){
return *(int*)a-*(int*)b;
}
int missingNumber(int* nums, int numsSize){
qsort(nums,numsSize,sizeof(int),cmp);
int i,ans=0;
if(nums[numsSize-1]!=numsSize){
return numsSize;
}
for(i=1;i<numsSize;++i){
if((nums[i]-nums[i-1])==2){
ans=nums[i]-1;
}
}
return ans;
}
时间复杂度
使用的是库函数qsort()
进行排序,时间复杂度是O(nlogn)
。
3.力扣1877
原题链接
https://leetcode-cn.com/problems/minimize-maximum-pair-sum-in-array/
题目概述
一个数对 (a,b) 的 数对和 等于 a + b 。最大数对和 是一个数对数组中最大的 数对和 。
比方说,如果我们有数对 (1,5) ,(2,3) 和 (4,4),最大数对和 为 max(1+5, 2+3, 4+4) = max(6, 5, 8) = 8 。
给你一个长度为 偶数 n 的数组 nums ,请你将 nums 中的元素分成 n / 2 个数对,使得:nums 中每个元素 恰好 在 一个 数对中,且
最大数对和 的值 最小 。
请你在最优数对划分的方案下,返回最小的 最大数对和 。
解题思路
先将原来的数组排序,然后取前面第 n 项,和倒数第 n 项相加,这样可以保证数对是最小的,就这样遍历一下整个数组之后就并输出最大的max就可以了。
源码剖析
int cmp(const void*a,const void*b){
return *(int*)a-*(int*)b;
}
int minPairSum(int* nums, int numsSize){
qsort(nums,numsSize,sizeof(int),cmp);
int max=0;
int i;
for(i=0;i<numsSize/2;++i){
if((nums[i]+nums[numsSize-1-i])>=max){
max = nums[i]+nums[numsSize-1-i];
}
}
return max;
}
时间复杂度
时间复杂度是O(nlogn)
。
4.力扣950
原题链接
https://leetcode-cn.com/problems/reveal-cards-in-increasing-order/
题目概述
牌组中的每张卡牌都对应有一个唯一的整数。你可以按你想要的顺序对这套卡片进行排序。
最初,这些卡牌在牌组里是正面朝下的(即,未显示状态)。
现在,重复执行以下步骤,直到显示所有卡牌为止:
从牌组顶部抽一张牌,显示它,然后将其从牌组中移出。
如果牌组中仍有牌,则将下一张处于牌组顶部的牌放在牌组的底部。
如果仍有未显示的牌,那么返回步骤 1。否则,停止行动。
返回能以递增顺序显示卡牌的牌组顺序。答案中的第一张牌被认为处于牌堆顶部。
解题思路
这题的思路是:找规律。随便找一例反向分析一下就可以得出这题进行的各种运算了。拿 1234 举例,经过一会摆弄可以得到,显示 1234 时的牌堆顺序是 1324 ,显示卡牌会经历如下的这些操作 1324-324-243-43-34-4
反过来看就是这样 4-34-43-243-324-1324
每一步经历的操作也就是 向前添加数据-末位元素提前-向前添加数据-末位元素提前-向前添加元素 最后一步是可以特殊化的,我们只看前四步,然后写出循环来实现这些功能就可以了。最后再补充回第一位,指的一说的是,每次添加的元素都是小于当前的数字中所有数字的,为了方便取出,可以提前对原来的数组先进行排序。
源码剖析
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int cmp(const void*a,const void*b){
return *(int*)a-*(int*)b;
}
int* deckRevealedIncreasing(int* deck, int deckSize, int* returnSize){
qsort(deck,deckSize,sizeof(int),cmp);
int *ret=(int*)malloc(sizeof(int)*deckSize);
int i,j,e=deckSize-1;
ret[deckSize-1] = deck[deckSize-1]; //在循环开始前初始化好第一个元素
for(i=1;i<deckSize-1;++i){ //至于循环进行次数见思路
ret[e-i]=deck[e-i]; //在前面添加一个新的数字
ret[e-i-1]=ret[e]; //将最后一个数字一道最前面
for(j=0;j<=i;++j){ //将所有的数据往后移动一格
ret[e-j] = ret[e-j-1];
}
}
ret[0] = deck[0]; //最终填充好第一位即可
*returnSize = deckSize;
return ret;
}
见代码注释。
时间复杂度
O(n^2)