【01 dp】A005_LC_生成數組(暴搜 / 記憶化 / dp)

一、Problem

Given three integers n, m and k. Consider the following algorithm to find the maximum element of an array of positive integers:
在這裏插入圖片描述
You should build the array arr which has the following properties:

  • arr has exactly n integers.
  • 1 <= arr[i] <= m where (0 <= i < n).
  • After applying the mentioned algorithm to arr, the value search_cost is equal to k.

Return the number of ways to build the array arr under the mentioned conditions. As the answer may grow large, the answer must be computed modulo 10^9 + 7.

Input: n = 2, m = 3, k = 1
Output: 6
Explanation: The possible arrays are [1, 1], [2, 1], [2, 2], [3, 1], [3, 2] [3, 3]

二、Solution

方法一:暴搜(超時)

  • 結束條件
    • 當前選擇個數等於 n 並且剩餘搜索代價爲 0,返回 1
    • 當前選擇個數不等於 n 但剩餘搜索代價爲小於 0,返回 0
  • 本層遞歸的責任
    • 找到最大值,結合最大值討論搜索代價。
  • 剪枝:如果剩餘可選數如果比剩餘搜索代價還要小,一定不存在剩餘搜索代價 cost=0cost = 0 的情況了。
class Solution {
	int mod = (int) 1e9 + 7, n, m, k;
	int dfs(int idx, int cur, int cost) {
        if (n - idx < cost)
            return 0;
		if (idx == n && cost == 0)
			return 1;
		if (cost < 0)
			return 0;
		int t = 0;
		for (int i = 1; i <= m; i++) {
			if (cur < i)  t += dfs(idx+1, i, cost-1);
			else 		  t += dfs(idx+1, cur, cost);
		}
		return t % mod;
	}
    public int numOfArrays(int n, int m, int k) {
        this.n = n; this.m = m; this.k = k;
		return dfs(0, -1, k);
    }
}

複雜度分析

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

方法二:記憶化

小心溢出…

class Solution {
	int mod = (int) 1e9 + 7, n, m;
    long memo[][][];
	long dfs(int idx, int cur, int cost) {
        if (n - idx < cost)         
        	return 0;
		if (idx == n && cost == 0)  
			return 1;
        if (cost < 0)
            return 0;
        if (memo[idx][cur][cost] != -1)
            return memo[idx][cur][cost];
		long t = 0;
		for (int i = 1; i <= m; i++) {
			if (cur < i)  t += dfs(idx+1, i, cost-1);
			else 		  t += dfs(idx+1, cur, cost);
		}
        t %= mod;
		return memo[idx][cur][cost] = t;
	}
    public int numOfArrays(int n, int m, int k) {
        this.n = n; this.m = m;
        memo = new long[55][150][55];
        for (int i = 0; i < memo.length; i++)
        for (int j = 0; j < memo[0].length; j++)
        for (int l = 0; l < memo[0][0].length; l++)
            memo[i][j][l] = -1;
		return (int) dfs(0, 0, k);
    }
}

複雜度分析

  • 時間複雜度:O(nmk)O(nmk)
  • 空間複雜度:O(nmk)O(nmk)

方法三:dp

  • 定義狀態
    • dp[]
  • 思考狀態轉移方程
    • dp[]
  • 思考初始化:
    • dp[]
  • 思考輸出:dp[]

參考:https://leetcode-cn.com/problems/build-array-where-you-can-find-the-maximum-exactly-k-comparisons/solution/java-onmkjie-fa-10ms-by-cjjohn/


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章