【線性 dp】B006_LC_可被三整除的最大和(三種餘數)

一、Problem

Given an array nums of integers, we need to find the maximum possible sum of elements of the array such that it is divisible by three.

Input: nums = [3,6,5,1,8]
Output: 18
Explanation: Pick numbers 3, 6, 1 and 8 their sum is 18 (maximum sum divisible by 3).

Constraints:

1 <= nums.length <= 4 * 10^4
1 <= nums[i] <= 10^4

二、Solution

這題真的想不到 dp,剛開始直接用暴搜做了,但是超時(ps:這題不能用二進制枚舉做,因爲 n 很大,1 << n 是不可能的)

方法一:暴搜

class Solution {
	long max; int n, a[];
	void dfs(int i, long cur) {
		if (i >= n)
			return;
		if (cur % 3 == 0 && cur > max)
			max = cur;
		for (int j = i+1; j < n; j++) {
			dfs(j, cur+a[j]);
		}
		dfs(i+1, cur);
	} 
    public int maxSumDivThree(int[] nums) {
    	a = nums;
    	n = a.length;
    	dfs(0, a[0]);
        return (int) max;
    }
}

複雜度分析

  • 時間複雜度:O(2n)O(2^n)
  • 空間複雜度:O(n)O(n)

方法二:dp

這題突破點是要想到:數字總和可劃分爲兩種大的狀態:

  • 可被 3 整除;
  • 不能被 3 整除,不能被 3 整除又分爲:
    • 除以 3 餘 1
    • 除以 3 餘 2

所以,dp 的狀態一共有 3 種

  • 定義狀態
    • f[i][0]f[i][0] 表示從前 ii 個數選若干個數後,模 3 餘 0 的最大和
    • f[i][1]f[i][1] 表示從前 ii 個數選若干個數後,模 3 餘 1 的最大和
    • f[i][2]f[i][2] 表示從前 ii 個數選若干個數後,模 3 餘 2 的最大和
  • 思考初始化:
    • f[0...n1][0...2]=0f[0...n-1][0...2] =0
  • 思考狀態轉移方程
    • f[i][j]=max(f[i][j], f[i1][j])f[i][j] = max(f[i][j],\ f[i-1][j])
    • 如果 f[i1][k]+a[i1] % 3f[i-1][k] + a[i-1]\ \%\ 3 的餘數爲 jj,則有 f[i][j]=max(f[i1][j], f[i1][k]+a[i1]f[i][j] = max(f[i-1][j],\ f[i-1][k] + a[i-1]
  • 思考輸出f[n][0]f[n][0]

注:這裏要注意的一點就是餘數爲 0 的狀態既可以從餘數爲 0/1/2 三種情況轉移過來,所以這三種都是要枚舉的。

class Solution {
    public int maxSumDivThree(int[] a) {
    	int n = a.length, f[][] = new int[n+1][3];
    	
    	for (int i = 1; i <= n; i++)
		for (int j = 0; j < 3; j++) {
            f[i][j] = f[i-1][j];
            for (int k = 0; k < 3; k++) {	//枚舉f的三種餘數的狀態k,因爲三種餘數狀態都有可能轉移到 j
                if ((f[i-1][k] + a[i-1]) % 3 == j)
                    f[i][j] = Math.max(f[i][j], f[i-1][k] + a[i-1]);
            }
        }
    	return f[n][0];
    }
}

複雜度分析

  • 時間複雜度:O(n)O(n)
  • 空間複雜度:O(n)O(n)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章