《五日集训》第三日——排序

前言

今日是五日集训的第三天,今日的训练内容是——排序。

解题报告

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)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值