双11狂欢大促

盲盒赢 定制羽绒服

开启惊喜盲盒,抽取你的专属好礼

— 惊喜奖品抢先看 —

九日集训Day6贪心算法

KissKernel KissKernel 墨衍会员 · AI 创作全网分发 墨衍智能分发 通过墨衍一键同步至各平台 可同步平台 CSDN微信公众号微博知乎掘金百家号博客园抖音小红书 你的文章也可以这样分发 墨衍会员 ¥399起/年,写一次发全网 我也要 + 加入社区

今天要学习的内容是贪心思想,贪心思想就是每次都是选取局部最优解,最后就可能得到全局最优解。

第一题

1913. 两个数对之间的最大乘积差

思路1:排序之后选最大和最小的两组数据之差

int cmp(const void* str1,const void* str2)
{
    return *(int*)str1-*(int*)str2;
}

int maxProductDifference(int* nums, int numsSize){

    qsort(nums,numsSize,sizeof(int),cmp);
    return (nums[numsSize-1]*nums[numsSize-2])-(nums[0]*nums[1]);
}

第二题

976. 三角形的最大周长

思路1:先排序数组,然后从大到小开始枚举,看最后三条边是不是满足两条小边相加>大边,如果不满足,则i--,减小最大边,继续判断,如果遍历完了数组都没有,那么数组元素都不构成三角形返回0即可。


int cmp(const void* str1,const void* str2)
{
    return *(int*)str1 - *(int*)str2;
}

int largestPerimeter(int* nums, int numsSize){

    qsort(nums,numsSize,sizeof(int),cmp);
    for(int i =numsSize-1;i>=2;i--)
    {
        if(nums[i]<nums[i-1]+nums[i-2])
        {
            return nums[i]+nums[i-1]+nums[i-2];
        }
    }
    return 0;

}

第三题

  1. 数组拆分 I

    思路:排序后,将相邻数进行分组,因为相邻两个数取最小值,可以保证砍掉的数字是相比较其他元素更小的,让最大的和次最大的成组,可以保证留下次最大的数字。

int cmp(const void* str1,const void* str2)
{
    return *(int*)str1 - *(int*)str2;
}


int arrayPairSum(int* nums, int numsSize){

    qsort(nums,numsSize,sizeof(int),cmp);
    int sum = 0;
    for(int i =0;i<numsSize;i+=2)
    {
        sum+=nums[i];
    }
    return sum;
}

第四题

881. 救生艇

思路:排序数组,从后向前,如果最后一个人的体重达到了limit就让他自己坐船走,如果小于limit就要判断,这个局部最重的和局部最轻的加在一起有没有超过limit,如果超过了,就让最重的走,如果没超过,就一起走。

int cmp(const void* str1,const void* str2)
{
    return *(int*)str1-*(int*)str2;
}

int numRescueBoats(int* people, int peopleSize, int limit){

    qsort(people,peopleSize,sizeof(int),cmp);
    int left = 0;
    int right = peopleSize-1;
    int count = 0;
    while(left<=right)
    {
        if(people[right]==limit)
        {
            right--;
            count++;
        }
        else
        {
            if(people[left]+people[right]<=limit)
            {
                left++;
                right--;
                count++;
            }
            else
            {
                right--;
                count++;
            }
        }
    }
    return count;
}

第五题

324. 摆动排序 II

思路:将数组拷贝一份然后排序,对原来数组的奇偶位进行插入,观察可以发现,偶数位插入最大值,所以定义一个指针从后向前遍历,排序好的数组,将最大值依次递减插入,
然后将插入完偶数位剩下的数组从后向前插入,这样可以保证,最大值对应小的那一半数字的最大值,完成贪心思想。

int cmp(const void* str1,const void* str2)
{
    return *(int*)str1-*(int*)str2;
}

void wiggleSort(int* nums, int numsSize){

    int arr[numsSize];
    memcpy(arr,nums,sizeof(int)*numsSize);
    qsort(arr,numsSize,sizeof(int),cmp);

    int arrsize = numsSize-1;
    for(int j =1;j<numsSize;j+=2)
    {
        nums[j] = arr[arrsize];
        arrsize--;
    }
    for(int i =0;i<numsSize;i+=2)
    {
        nums[i] = arr[arrsize];
        arrsize--;
    }   
}

第六题

455. 分发饼干

思路:将饼干和小孩都排序,先拿最小的饼干给最容易饱的小孩,如果饱了,计数器++,不饱就换一块更大的。直到饼干没了或者小孩子都饱了,循环结束

int cmp(const void* str1,const void* str2)
{
    return *(int*)str1-*(int*)str2;
}

int findContentChildren(int* g, int gSize, int* s, int sSize){
    qsort(g,gSize,sizeof(int),cmp);
    qsort(s,sSize,sizeof(int),cmp);
    int cookie = 0;
    int ans = 0;
    int i = 0;
    while(cookie<sSize&&i<gSize)
    {
        if(g[i]>s[cookie])//没吃饱
        {
            cookie++;
        }
        else//吃饱了
        {
            i++;
            cookie++;
            ans++;
        }
    }
    return ans;
}

第七题

1827. 最少操作使数组递增

思路是:遍历每个数组元素,如果数组元素前一个大于该元素,就把数组元素递增至nums[i-1]+1;然后计数器增加nums[i-1]+1-nums[i]即可(也就是记录从nums[i]到nums[i]+1要加多少个1即可)

int minOperations(int* nums, int numsSize){
    if(numsSize==1)
    return 0;
    
    int cnt = 0;
    int i = 1;
    while(i<numsSize)
    {
        if(nums[i]<=nums[i-1])
        {
            cnt+=nums[i-1]-nums[i]+1;
            nums[i]=nums[i-1]+1;
        }
        else
        {
            i++;
        }
    }
    return cnt;
}

第八题

945. 使数组唯一的最小增量

思路:先排序数组,然后判断数组的每个元素和前一个元素相比是不是比前一个大,如果不是就递增到nums[i]+1;记录递增次数,最后返回即可。

int cmp(const void* str1,const void* str2)
{
    return *(int*)str1-*(int*)str2;
}

int minIncrementForUnique(int* nums, int numsSize){
    qsort(nums,numsSize,sizeof(int),cmp);
    int ans = 0;
    int i = 1;
    while(i<numsSize)
    {
        if(nums[i]<=nums[i-1])
        {
            ans+=nums[i-1]-nums[i]+1;
            nums[i] = nums[i-1]+1;         
            i++;
        }
        else
        i++;
    }
    return ans;
}

第九题

611. 有效三角形的个数

思路是:先排序,然后枚举第一条和第二条第三条边,判断如果第三条边>前两边之和,就结束第三层循环,用计数器记录第二条和第三条之间,有效的有几条,加到计数器上。然后将第二条进行++。继续枚举第三条。如果第二条和第三条重合了就自增第三条。

    
int cmp(const void* str1,const void* str2)
{
    return *(int*)str1-*(int*)str2;
}


int triangleNumber(int* nums, int numsSize){
    qsort(nums,numsSize,sizeof(int),cmp);
    int one = 0;
    int two = 0;
    int three = 0;
    int count = 0;
    for(one = 0;one<numsSize;one++)
    {
        two = one+1;
        three = two +1;
        while(two<numsSize)
        {
            while(three<numsSize)
            {
                if(nums[one]+nums[two]<=nums[three])
                {
                    break;
                }
                three++;
            }
            count+=three-two-1;
            two++;
            if(two==three)
            three++;
        }
    }
    return count;
}
...全文
评论
收藏 已收藏
分享
返回顶部
KissKernel
万人千题 64,203 成员 15,010 内容