【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/


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