美文网首页算法
1262. 可被三整除的最大和

1262. 可被三整除的最大和

作者: 红树_ | 来源:发表于2023-06-18 15:50 被阅读0次

LC每日一题,参考1262. 可被三整除的最大和,难度分1762。

题目

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

输入:nums = [3,6,5,1,8]
输出:18
解释:选出数字 3, 6, 1 和 8,它们的和是 18(可被 3 整除的最大和)。
输入:nums = [4]
输出:0
解释:4 不能被 3 整除,所以无法选出数字,返回 0。
输入:nums = [1,2,3,4,4]
输出:12
解释:选出数字 1, 3, 4 以及 4,它们的和是 12(可被 3 整除的最大和)。

解题思路

  • 贪心:反向思考,求和后减去一些比较小的数使和最大。
  • 动态规划:定义dp[i][j]表示[0,i)中余数为j的最大和,找转移方程。

贪心

class Solution {
    public int maxSumDivThree(int[] nums) {
        int sum = 0;
        //计算最小的两个余数1和最小的两个余数2
        int pre1 = 0,pre2 = 0,pre3 = 0,pre4 = 0;
        for(int i : nums) {
            sum += i;
            if(i%3 == 1) {
                if(pre1 == 0) pre1 = i;
                else {
                    if(i < pre1) {
                        if(pre2 == 0) pre2 = pre1;
                        else pre2 = Math.min(pre1,pre2);
                        pre1 = i;
                    }else {
                        if(pre2 == 0) pre2 = i;
                        else pre2 = Math.min(i,pre2);
                    }
                }
            }
            else if(i%3 == 2){
                if(pre3 == 0) pre3 = i;
                else {
                    if(i < pre3) {
                        if(pre4 == 0) pre4 = pre3;
                        else pre4 = Math.min(pre3,pre4);
                        pre3 = i;
                    }else {
                        if(pre4 == 0) pre4 = i;
                        else pre4 = Math.min(i,pre4);
                    }
                }
            }
        }
        if(sum%3 == 0) return sum;
        int min = sum;
        if(sum%3 == 1) {
            if(pre1 > 0) min = Math.min(min,pre1);
            if(pre3 > 0 && pre4 > 0) min = Math.min(min,pre3+pre4);
        }else {
            if(pre1 > 0 && pre2 > 0) min = Math.min(min,pre1+pre2);
            if(pre3 > 0) min = Math.min(min,pre3);
        }
        return sum - min;
    }
}

复杂度分析

  • 时间复杂度:O(n)n为数组长度,一重循环遍历。
  • 空间复杂度:O(1)

动态规划

class Solution {
    public int maxSumDivThree(int[] nums) {
        int n = nums.length;
        //动态规划 dp[i][j]表示前i个数余数为j的最大值
        int[][] dp = new int[n+1][3];
        dp[0][1]=Integer.MIN_VALUE; // 不合法设为负无穷
        dp[0][2]=Integer.MIN_VALUE;
        for(int i = 0; i < n; i++) {
            // if(nums[i]%3 == 0){
            //     for(int j = 0; j < 3; j++) dp[i+1][j] = dp[i][j] + nums[i];
            // }else if(nums[i]%3 == 1) {
            //     dp[i+1][0] = Math.max(dp[i][0],dp[i][2]+nums[i]);
            //     dp[i+1][1] = Math.max(dp[i][1],dp[i][0]+nums[i]);
            //     dp[i+1][2] = Math.max(dp[i][2],dp[i][1]+nums[i]);
            // }else {
            //     dp[i+1][0] = Math.max(dp[i][0],dp[i][1]+nums[i]);
            //     dp[i+1][1] = Math.max(dp[i][1],dp[i][2]+nums[i]);
            //     dp[i+1][2] = Math.max(dp[i][2],dp[i][0]+nums[i]);
            // }
            for(int j = 0; j < 3; j++){
                //选或不选取最大值递推
                dp[i+1][j] = Math.max(dp[i][j],dp[i][(j-nums[i]%3 + 3)%3]+nums[i]);
            }
        }
        return dp[n][0];
    }
}

复杂度分析

  • 时间复杂度:O(n),一重循环遍历。
  • 空间复杂度:O(n)dp数组空间。

2023.06.19

相关文章

网友评论

    本文标题:1262. 可被三整除的最大和

    本文链接:https://www.haomeiwen.com/subject/gycsydtx.html