力扣(LeetCode)1753. 移除石子的最大得分(C++\C)

贪心+模拟

贪心思路 : 循环从石子数量最多的两堆取石子,直到有两堆以上(含两堆)空石子,维护取子次数,即是答案。贪心的正确性,暂无数学证明。直觉来看,这么做是对的。

CPP

class Solution {
public:
    int maximumScore(int a, int b, int c) {
        int f[3] = {a,b,c};
        sort(f,f+3);
        int ans = 0;
        while(f[0]||f[1]){
            ans++;
            f[1]--,f[2]--;
            sort(f,f+3);
        }
        return ans;
    }
};

C

int cmp(const void *a,const void *b){
    return *(int*)a-*(int*)b;
}
int maximumScore(int a, int b, int c){
    int f[3] = {a,b,c};
    qsort(f,3,sizeof(int),cmp);
    int ans = 0;
    while(f[0]||f[1]){
        ans++;
        f[1]--,f[2]--;
        qsort(f,3,sizeof(int),cmp);
    }
    return ans;
}
  1. 时间复杂度 : O ( m ) O(m) O(m) m m m 是最多石子的那一堆的石子数量, 最坏时间复杂度 O ( m ) O(m) O(m)
  2. 空间复杂度 : O ( 1 ) O(1) O(1) , 只使用常量级空间 。

贪心+数学

a , b , c a,b,c a,b,c 存入数组 f f f 按升序排序。如果 f [ 0 ] + f [ 1 ] < = f [ 2 ] f[0]+f[1]<=f[2] f[0]+f[1]<=f[2] ,根据贪心思路,每次取最大两堆的石子,就是循环从 f [ 2 ] f[2] f[2] m a x ( f [ 0 ] , f [ 1 ] ) max(f[0],f[1]) max(f[0],f[1]) 取石子。取石子的次数 = f [ 0 ] + f [ 1 ] =f[0]+f[1] =f[0]+f[1]

如果 f [ 0 ] + f [ 1 ] > f [ 2 ] f[0]+f[1]>f[2] f[0]+f[1]>f[2] ,可以想象,这种情况一定可以最大限度的取完所有石子——①三堆都取完 ②某一堆剩 1 1 1 个石子,其他两堆取完。根据贪心思路,每次取最大两堆,它的终止条件就是①或②。取石子的次数,只和终止状态下,三堆剩余的石子数有关。我们可以随便取,只要达到①或②的终止状态,就是最优解法。

考虑先从 f [ 2 ] f[2] f[2] m a x ( f [ 0 ] , f [ 1 ] ) max(f[0],f[1]) max(f[0],f[1]) 取石子, f [ 2 ] f[2] f[2] 一定会被取完,因为 f [ 0 ] + f [ 1 ] > f [ 2 ] f[0]+f[1]>f[2] f[0]+f[1]>f[2] 。取完 f [ 2 ] f[2] f[2] 时, f [ 0 ] f[0] f[0] f [ 1 ] f[1] f[1] 的差值不大于 1 1 1 ,接着从 f [ 0 ] f[0] f[0] f [ 1 ] f[1] f[1] 中取石子,最后也能达到三堆都取完或者某一堆剩 1 1 1 个石子,其他两堆取完的状态 。取石子的次数 = ( f [ 0 ] + f [ 1 ] + f [ 2 ] ) ÷ 2 =(f[0]+f[1]+f[2])\div 2 =(f[0]+f[1]+f[2])÷2

CPP

class Solution {
public:
    int maximumScore(int a, int b, int c) {
        int f[3] = {a,b,c};
        sort(f,f+3);
        if(f[0]+f[1]<=f[2]) return f[0] + f[1];
        return f[0]+f[1]+f[2]>>1;
    }
};

C

int cmp(const void *a,const void *b){
    return *(int*)a-*(int*)b;
}
int maximumScore(int a, int b, int c){
    int f[3] = {a,b,c};
    qsort(f,3,sizeof(int),cmp);
    if(f[0]+f[1]<=f[2]) return f[0] + f[1];
    return f[0]+f[1]+f[2]>>1;
}
  1. 时间复杂度 : O ( 1 ) O(1) O(1) , 只进行常量次计算 。
  2. 空间复杂度 : O ( 1 ) O(1) O(1) , 只使用常量级空间 。

AC

力扣(LeetCode)1753. 移除石子的最大得分(C++\C)_第1张图片
力扣(LeetCode)1753. 移除石子的最大得分(C++\C)_第2张图片

致语

  • 理解思路很重要!
  • 欢迎读者在评论区留言,墨染看到就会回复的。

你可能感兴趣的:(墨染leetcode,leetcode,c++,算法,贪心算法)