LeetCode·1262. 可被三整除的最大和·贪心

给定一个整数数组,找出能被3整除的元素最大和。如果数组元素和能被3整除,直接返回其和;否则,通过移除数组中某些数使和能被3整除,求最大可能的和。文章介绍了如何通过分类讨论和排序来解决此问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

作者:小迅
链接:https://leetcode.cn/problems/greatest-sum-divisible-by-three/solutions/2314049/tan-xin-zhu-shi-chao-ji-xiang-xi-by-xun-r0n76/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

题目

 

思路

题意 -> 给你一个整数数组 nums,请你找出并返回能被三整除的元素最大和。

由于数组中没有负数,如果整个数组的元素和 s 可以被 3 整除,那么 s 就是最大的元素和。

否则,如果 s 不能被 3 整除,那就看看能否让 s 减去某些 nums[i],使得 s 可以被 3 整除。

找到所有 nums[i] mod 3=1 的 nums[i],放到数组 a1 中;找到所有 nums[i] mod 3=2 的 nums[i],放到数组 a2中。对 a1和 a2 从小到大排序。分类讨论:

  • 如果 s mod 3=1:
    • 如果 a1 不为空,那么答案可能是 s−a1[0];
    • 如果 a2 中至少有两个数,那么答案可能是 s−a2[0]−a2[1];
    • 这两种情况取最大值。
    • 如果没有这样的数,返回 0。
  • 如果 s mod 3=2:
    • 如果 a2 不为空,那么答案可能是 s−a2[0];
    • 如果 a1 中至少有两个数,那么答案可能是 s−a1[0]−a1[1];
    • 这两种情况取最大值。
    • 如果没有这样的数,返回 0。

代码实现时,如果 s mod 3=2,那么可以交换数组 a1 和 a2,从而复用同一套逻辑。

代码注释超级详细

代码


static int cmp(const void *a, const void *b) {//升序
    return *(int *)a - *(int *)b;
}

int maxSumDivThree(int* nums, int numsSize) {
    int a[3][numsSize];
    memset(a, 0, sizeof(a));
    int i = 0, j = 0, sum = 0;//初始化
    for (int m = 0; m < numsSize; ++m) {//枚举所有元素
        sum += nums[m];//统计元素和
        if (nums[m] % 3 == 1) {//保存当前元素的余数
            a[nums[m] % 3][i++] = nums[m];
        } else if (nums[m] % 3 == 2) {
            a[nums[m] % 3][j++] = nums[m];
        }
    }
    if (sum % 3 == 0) return sum;//正好完成整除
    qsort(a[1], i, sizeof(a[1][0]), cmp);
    qsort(a[2], j, sizeof(a[2][0]), cmp);//升序
    int *a1 = a[1], *a2 = a[2];//指针交换位置非常方便
    if (sum % 3 == 2) {//情况二,交换指针
        a1 = a[2];
        a2 = a[1];
        int temp = i; 
        i = j;
        j = temp;
    }

    int ans = i == 0 ? 0 : sum - a1[0];//情况一判断
    if (j > 1) ans = fmax(ans, sum - a2[0] - a2[1]);//情况二判断
    return ans;
}


作者:小迅
链接:https://leetcode.cn/problems/greatest-sum-divisible-by-three/solutions/2314049/tan-xin-zhu-shi-chao-ji-xiang-xi-by-xun-r0n76/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值