📌  相关文章
📜  从给定数组中可被K整除的元素的最大和(1)

📅  最后修改于: 2023-12-03 14:49:27.397000             🧑  作者: Mango

从给定数组中可被K整除的元素的最大和

对于一个给定的整数数组和一个整数 K,你需要找到该数组中和能够被 K 整除的最大值。

解题思路
方法一:暴力枚举

我们可以先对数组进行排序,然后从大到小枚举数组中的元素,依次累加元素的值,同时判断累加的和是否能够被 K 整除。

时间复杂度为 O(nlogn + n^2)

方法二:前缀和

我们可以先计算出数组的前缀和数组 sum,其中 sum[i] 表示前 i 个元素的和。然后我们可以通过计算 sum[i] 和 sum[j] 的差值是否能够被 K 整除来判断从 i 到 j 的区间和是否能够被 K 整除。

时间复杂度为 O(n)

代码实现
方法一:暴力枚举
public int maxSumDivK(int[] nums, int k) {
    Arrays.sort(nums);
    int n = nums.length;
    int ans = 0;
    for (int i = n - 1; i >= 0; i--) {
        int sum = nums[i];
        if (sum % k == 0) {
            return sum;
        }
        for (int j = i - 1; j >= 0; j--) {
            sum += nums[j];
            if (sum % k == 0) {
                ans = Math.max(ans, sum);
                break;
            }
        }
    }
    return ans;
}
方法二:前缀和
public int maxSumDivK(int[] nums, int k) {
    int n = nums.length;
    int[] sum = new int[n + 1];
    for (int i = 1; i <= n; i++) {
        sum[i] = sum[i - 1] + nums[i - 1];
    }
    int[][] dp = new int[n + 1][k];
    dp[0][0] = 0;
    for (int i = 1; i <= n; i++) {
        for (int j = 0; j < k; j++) {
            dp[i][j] = dp[i - 1][j];
            int mod = ((sum[i] % k) + k) % k;
            int preMod = ((sum[i - 1] % k) + k) % k;
            if (j == preMod) {
                dp[i][j] = Math.max(dp[i][j], dp[i - 1][j] + nums[i - 1]);
            }
            if (j == mod) {
                dp[i][j] = Math.max(dp[i][j], dp[i - 1][j] + nums[i - 1]);
            }
        }
    }
    return dp[n][0];
}
总结

本题可以采用两种不同的算法来求解。方法一采用了暴力枚举的方式,时间复杂度为 O(nlogn + n^2);方法二采用了前缀和的方式,时间复杂度为 O(n)。方法二的时间复杂度更优,但是需要使用到动态规划的思想,相对来说难度较大。