[Leetcode Weekly Contest]202

链接:LeetCode

[Leetcode]5185. 存在连续三个奇数的数组

给你一个整数数组 arr,请你判断数组中是否存在连续三个元素都是奇数的情况:如果存在,请返回 true ;否则,返回 false 。

暴力即可。

class Solution {
public:
    bool threeConsecutiveOdds(vector<int>& arr) {
        int count=0;
        for(auto n:arr){
            if(n&1){
                count ++;
            }
            else{
                count = 0;
            }
            if(count==3){
                return true;
            }
        }
        return false;
    }
};

[Leetcode]5488. 使数组中所有元素相等的最小操作数

存在一个长度为 n 的数组 arr ,其中\(arr[i] = (2 * i) + 1 ( 0 <= i < n )\)
一次操作中,你可以选出两个下标,记作 x 和 y ( 0 <= x, y < n )并使\(arr[x]\)减去 1 、\(arr[y]\)加上 1 (即\(arr[x] -=1\)\(arr[y] += 1\))。最终的目标是使数组中的所有元素都 相等 。题目测试用例将会 保证 :在执行若干步操作后,数组中的所有元素最终可以全部相等。
给你一个整数 n,即数组的长度。请你返回使数组 arr 中所有元素相等所需的 最小操作数 。

找规律。数组 arr 满足\(arr[i] = (2 * i) + 1 ( 0 <= i < n )\)。其所有元素的累加和为 (n + 2)*n。有累加和可知,操作完成后,每个元素均为 n+2。操作前,arr 中总共有 x 个元素小于 n+2,x = n/2-1。这 x 个元素的累加和为(n+3)(n-1)/4。操作后,前 x 个元素的累加和为 (n+2)(n-2)/2。因为每次操作,小于 n+2 的元素的累加和会增加一,所以两和作差即为答案,(n^2)/4。(整数相除会向下取整哦)。

class Solution {
public:
    int minOperations(int n) {
        return n*n/4;
    }
};

[Leetcode]5489. 两球之间的磁力

在代号为 C-137 的地球上,Rick 发现如果他将两个球放在他新发明的篮子里,它们之间会形成特殊形式的磁力。Rick 有 n 个空的篮子,第 i 个篮子的位置在\(position[i]\),Morty 想把 m 个球放到这些篮子里,使得任意两球间 最小磁力 最大。
已知两个球如果分别位于 x 和 y ,那么它们之间的磁力为\(|x - y|\)
给你一个整数数组 position 和一个整数 m ,请你返回最大化的最小磁力。

二分查找。题意求最大化最小,类似这样的求最大化最小值、最小化最大值等都可以用二分搜索解决。首先要找到二分搜索的边界,根据题意,要返回的是最小磁力,所以第一步要找到最小磁力的最小可能取值和最大可能取值。
对于最小可能取值,当然就是给定数组中距离最近的两个位置之间的磁力,所以对数组进行排序,并遍历数组找到相邻两个位置的最小距离。对于最大可能取值,一共有m个球,所以有 m - 1 个间隔,最大的可能取值便是最平均的取值,所以根据给定数组最大值与最小值之差与间隔数的比值计算出平均距离,就是给定的最大可能取值。
确定好了边界后,每次二分搜索时需要判断当前计算值是否满足条件,这里我们引入 check 函数,对当前计算出的最小磁力进行验证。验证过程使用贪心算法,遍历数组,若找到两位置之间距离大于等于最小磁力,则计数值加1,最后只需要判断总计数值是否大于等于给定间隔数 m - 1即可。
在判断计算值满足条件与否之后,我们要对二分搜索边界进行转化,由于题目要求的是最大化的最小磁力,所以若当前计算出的最小磁力满足条件,我们要将左边界右移,去判断稍大一点的数值是否满足条件;若当前计算出的最小磁力不满足条件,我们要将右边界左移,判断稍小的数值是否满足条件。由于每次满足条件后左边界右移,所以左边界的左边一个数值是一定满足条件的,所以最后返回值为 l - 1,具体返回值根据边界移动的判定规则进行判断。

class Solution {
public:
    bool check(vector<int>& position,int m,int minDiff) {
        int n=position.size(),count=1,target=position[0]+minDiff;
        for(auto n:position){
            if(n>=target) {
                target=n+minDiff;
                count ++;
            }
        }
        return count>=m;
    }

    int maxDistance(vector<int>& position, int m) {
        sort(position.begin(),position.end());
        int n=position.size();
        int diff  = position[n-1] - position[0];
        if(m==2){
            return diff;
        }
        int le=INT_MAX,hi=diff/(m-1);
        for(int i=1;i<n;++i){
            le=min(le,position[i]-position[i-1]);
        }
        while(le<=hi){
            int mid=le+((hi-le)>>1);
            if(check(position,m,mid)) le=mid+1;
            else hi=mid-1;
        }
        return le-1;
    }
};

[Leetcode]5490. 吃掉 N 个橘子的最少天数

厨房里总共有 n 个橘子,你决定每一天选择如下方式之一吃这些橘子:

  • 吃掉一个橘子。
  • 如果剩余橘子数 n 能被 2 整除,那么你可以吃掉 n/2 个橘子。
  • 如果剩余橘子数 n 能被 3 整除,那么你可以吃掉 2*(n/3) 个橘子。

每天你只能从以上 3 种方案中选择一种方案。
请你返回吃掉所有 n 个橘子的最少天数。

动态规划。实际上可以通过记忆化搜索的方法解决。

class Solution {
public:
    unordered_map<int,int> um;

    int minDays(int n) {
        if(n==0) return 0;
        if(n==1) return 1;
        if(um.count(n)) return um[n];
        um[n] = min(minDays(n/2)+n%2,minDays(n/3)+n%3)+1;
        return um[n];
    }
};

参考:
Leetcode

posted @ 2020-08-16 22:30  Jamest  阅读(166)  评论(0编辑  收藏  举报