七月集训(4)贪心

1.LeetCode:2078. 两栋颜色不同且距离最远的房子

原题链接


        街上有 n 栋房子整齐地排成一列,每栋房子都粉刷上了漂亮的颜色。给你一个下标从 0 开始且长度为 n 的整数数组 colors ,其中 colors[i] 表示第 i 栋房子的颜色。

        返回 两栋 颜色 不同 房子之间的 最大 距离。

        第 i 栋房子和第 j 栋房子之间的距离是 abs(i - j) ,其中 abs(x) 是 x 的绝对值。

        示例 1:

        输入:colors = [1,1,1,6,1,1,1]

        输出:3

        示例 2:

        输入:colors = [1,8,3,8,3]

        输出:4

        示例 3:

        输入:colors = [0,1]

        输出:1

        提示:

        n == colors.length

        2 <= n <= 100

        0 <= colors[i] <= 100

        生成的测试数据满足 至少 存在 2 栋颜色不同的房子


        看数据量n只有100,那么就不需要什么复杂的算法了,直接枚举所有位置的房子,去数组中向右边找与他颜色不同的房子并且维护ans。(为什么不像前找是因为距离是相互的,如果该位置与之前的房子距离为答案,那么在之前就已经找过了,不用再判断了。)

class Solution {
public:
    int maxDistance(vector<int>& colors) {
        int ans=-0x3f3f3f3f;
        for(int i=0;i<colors.size();++i){
            for(int j=i+1;j<colors.size();++j){
                if(colors[j]!=colors[i])
                ans=max(ans,abs(j-i));
            }
        }
        return ans;
    }
};

2.LeetCode:561. 数组拆分 I

原题链接


        给定长度为 2n 的整数数组 nums ,你的任务是将这些数分成 n 对, 例如 (a1, b1), (a2, b2), …, (an, bn) ,使得从 1 到 n 的 min(ai, bi) 总和最大。
返回该 最大总和 。

        示例 1:

        输入:nums = [1,4,3,2]

        输出:4

        示例 2:

        输入:nums = [6,2,6,5,1,2]

        输出:9

        提示:

        1 <= n <= 1e4

        nums.length == 2 * n

        -1e4 <= nums[i] <= 1e4


        这个就是典型的贪心题目了,按照题目要求,数组中最小的元素一定会被加入到答案中,而最大的元素一定不会被加入,所以我们先把数组排序,那么我们会发现,每次加入数组的第一小和第二大并将这第一小第二小,第一大第二大(尽量删除最小和最大的那组)从数组中删去后,新加入的数就是剩余元素的第一小和第二大。

        这样我们就发现了我们每次加入到答案中的数字是数组中每两个数字的前一个,那么按照这个发现遍历数组即可。

class Solution {
public:
    int arrayPairSum(vector<int>& nums) {
        sort(nums.begin(),nums.end());
        int n=nums.size();
        int ans=0;
        for(int i=0;i<n;i+=2){
            ans+=nums[i];
        }
        return ans;
    }
};

3.LeetCode:1323. 6 和 9 组成的最大数字

原题链接


        给你一个仅由数字 6 和 9 组成的正整数 num。

        你最多只能翻转一位数字,将 6 变成 9,或者把 9 变成 6 。

        请返回你可以得到的最大数字。

        示例 1:

        输入:num = 9669

        输出:9969 。

        示例 2:

        输入:num = 9996

        输出:9999

        示例 3:

        输入:num = 9999

        输出:9999

        提示:

        1 <= num <= 10^4

        num 每一位上的数字都是 6 或者 9 。


        没什么好说的,吧最高位的6变成9即可

class Solution {
public:
    int maximum69Number (int num) {
        vector<int> tmp;
        while(num){
            tmp.push_back(num%10);
            num/=10;
        }
        for(int i=tmp.size()-1;i>=0;--i){
            if(tmp[i]==6){
                tmp[i]=9;
                break;
            }
        }
        int ans=0;
        for(int i=tmp.size()-1;i>=0;--i ){
            ans=ans*10+tmp[i];
        }
        return ans;
    }
};

4.LeetCode:942. 增减字符串匹配

原题链接


        由范围 [0,n] 内所有整数组成的 n + 1 个整数的排列序列可以表示为长度为 n 的字符串 s ,其中:

        如果 perm[i] < perm[i + 1] ,那么 s[i] == ‘I’

        如果 perm[i] > perm[i + 1] ,那么 s[i] == ‘D’

        给定一个字符串 s ,重构排列 perm 并返回它。如果有多个有效排列perm,则返回其中 任何一个 。

        示例 1:

        输入:s = “IDID”

        输出:[0,4,1,3,2]

        示例 2:

        输入:s = “III”

        输出:[0,1,2,3]

        示例 3:
        输入:s = “DDI”

        输出:[3,2,0,1]

        提示:

        1 <= s.length <= 1e5

        s 只包含字符 “I” 或 “D”


        先定义max=perm.size(),min=0,然后遍历字符串,如果是"I"就在答案中加入min++,如果是"D"就加入max–,最后判断字符串最后一位,如果是"I"就加入min否则加入max。

        这样做是因为如果是"I"的话我们尽量让当前位置的数最小即可,如果是"D"的话我们尽量让当前位置最大即可。但是这样数组最后只有n个数字。不过这个时候随便加入min或者max即可,因为min和max在构造的过程中是不断逼近的,最后一定是相等的。

        具体论证的话我们设字符串中有x个"I",y个"D"我们有如下条件:
{ x + y = n ( 1 ) m i n = x ( 2 ) m a x = n − y ( 3 ) \begin{cases} x+y=n&(1)\\ min=x&(2)\\ max=n-y&(3) \end{cases} x+y=nmin=xmax=ny(1)(2)(3)

        由(1)可以得到x=n-y
        由(2)可知x=min
        由(1),(3)得x=max,由此可以得到最终得max和min是相等的加入哪一个都无所谓

class Solution {
public:
    vector<int> diStringMatch(string s) {
        vector<int> ans;
        int min=0,max=s.size();
        for(int i=0;i<s.size();++i){
            ans.push_back(s[i]=='I'?min++:max--);
        }
        ans.push_back(min);
        return ans;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值