九日集训Day6贪心算法

我不是很喜欢聊天 2022-05-20 23:49:42

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

第一题

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;
}
...全文
55 回复 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

64,172

社区成员

发帖
与我相关
我的任务
社区描述
学习「 算法 」的捷径就是 「 题海战略 」,社区由「 夜深人静写算法 」作者创建,三年ACM经验,校集训队队长,亚洲区域赛金牌,世界总决赛选手。社区提供系统的训练,答疑解惑,面试经验,大厂内推等机会
社区管理员
  • 英雄哪里出来
  • 芝麻粒儿
  • Amy卜bo皮
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

QQ群:480072171

英雄算法交流 8 群

 

试试用AI创作助手写篇文章吧