2024-01-03:用go语言,给你两个长度为 n 下标从 0 开始的整数数组 cost 和 time,
分别表示给 n 堵不同的墙刷油漆需要的开销和时间。你有两名油漆匠,
一位需要 付费 的油漆匠,刷第 i 堵墙需要花费 time[i] 单位的时间,
开销为 cost[i] 单位的钱。
一位 免费 的油漆匠,刷 任意 一堵墙的时间为 1 单位,开销为 0,
但是必须在付费油漆匠 工作 时,免费油漆匠才会工作。
请你返回刷完 n 堵墙最少开销为多少?
输入:cost = [1,2,3,2], time = [1,2,3,2]。
输出:3。
来自力扣。2742. 给墙壁刷油漆。
答案2024-01-03:
来自左程云。
灵捷3.5
paintWalls1
函数1.paintWalls1
函数是基于递归方法的解决方案。
2.在 process1
函数中,通过递归方式将每种情况下的最小开销计算出来。
3.递归调用时考虑两种情况,选择当前墙刷或者不刷,计算出最小开销。
4.该方法在递归调用的过程中可能会有很多重复计算,效率可能不高。
paintWalls2
函数1.paintWalls2
函数采用了记忆化搜索的方式。
2.定义了一个二维数组 dp
用于记录已经计算过的结果,避免重复计算。
3.通过递归+记忆化搜索的方式优化了重复计算,提高了效率。
paintWalls3
函数1.paintWalls3
函数采用了动态规划的方式。
2.使用一个一维数组 dp
保存不同墙数下的最小开销。
3.结合循环和动态递推的方式,迭代计算每墙的最小开销,直到第 n 墙。
时间复杂度:
paintWalls1
使用了递归,可能有大量重复计算,其时间复杂度为 O(2^n)。
paintWalls2
和 paintWalls3
使用了记忆化搜索和动态规划,时间复杂度都为 O(n^2),其中 n 为墙的数量。
空间复杂度:
paintWalls1
和 paintWalls2
的额外空间复杂度为 O(n^2),因为它们都使用了二维数组存储中间结果。
paintWalls3
的额外空间复杂度为 O(n),因为它只用了一个一维数组保存中间结果。
package main import ( "fmt" "math" ) // paintWalls1 represents the first function from the given Java code. func paintWalls1(cost []int, time []int) int { return process1(cost, time, 0, len(cost)) } // process1 is the recursive function as mentioned in the Java code. func process1(cost []int, time []int, i int, s int) int { if s <= 0 { return 0 } // s > 0 if i == len(cost) { return math.MaxInt32 } else { p1 := process1(cost, time, i+1, s) p2 := math.MaxInt32 next2 := process1(cost, time, i+1, s-1-time[i]) if next2 != math.MaxInt32 { p2 = cost[i] + next2 } return int(math.Min(float64(p1), float64(p2))) } } // paintWalls2 is the second function from the given Java code. func paintWalls2(cost []int, time []int) int { n := len(cost) dp := make([][]int, n+1) for i := range dp { dp[i] = make([]int, n+1) for j := range dp[i] { dp[i][j] = -1 } } return process2(cost, time, 0, n, dp) } // process2 represents the recursive function in the second approach of the Java code. func process2(cost []int, time []int, i int, s int, dp [][]int) int { if s <= 0 { return 0 } if dp[i][s] != -1 { return dp[i][s] } var ans int if i == len(cost) { ans = math.MaxInt32 } else { p1 := process2(cost, time, i+1, s, dp) p2 := math.MaxInt32 next2 := process2(cost, time, i+1, s-1-time[i], dp) if next2 != math.MaxInt32 { p2 = cost[i] + next2 } ans = int(math.Min(float64(p1), float64(p2))) } dp[i][s] = ans return ans } // paintWalls3 is the third function from the given Java code. func paintWalls3(cost []int, time []int) int { n := len(cost) dp := make([]int, n+1) for i := range dp { dp[i] = math.MaxInt32 } dp[0] = 0 for i := n - 1; i >= 0; i-- { for s := n; s >= 1; s-- { if s-1-time[i] <= 0 { dp[s] = int(math.Min(float64(dp[s]), float64(cost[i]))) } else if dp[s-1-time[i]] != math.MaxInt32 { dp[s] = int(math.Min(float64(dp[s]), float64(cost[i]+dp[s-1-time[i]]))) } } } return dp[n] } func main() { cost := []int{1, 2, 3, 2} time := []int{1, 2, 3, 2} fmt.Println("Result 1:", paintWalls1(cost, time)) fmt.Println("Result 2:", paintWalls2(cost, time)) fmt.Println("Result 3:", paintWalls3(cost, time)) }
fn paint_walls1(cost: Vec<i32>, time: Vec<i32>) -> i32 { process1(&cost, &time, 0, cost.len() as i32) } fn process1(cost: &Vec<i32>, time: &Vec<i32>, i: i32, s: i32) -> i32 { if s <= 0 { return 0; } if (i as usize) == cost.len() { return i32::MAX; } else { let p1 = process1(cost, time, i + 1, s); let mut p2 = i32::MAX; let next2 = process1(cost, time, i + 1, s - 1 - time[i as usize]); if next2 != i32::MAX { p2 = cost[i as usize] + next2; } return p1.min(p2); } } fn paint_walls2(cost: Vec<i32>, time: Vec<i32>) -> i32 { let n = cost.len(); let mut dp = vec![vec![-1; n + 1]; n + 1]; process2(&cost, &time, 0, n as i32, &mut dp) } fn process2(cost: &Vec<i32>, time: &Vec<i32>, i: i32, s: i32, dp: &mut Vec<Vec<i32>>) -> i32 { if s <= 0 { return 0; } if dp[i as usize][s as usize] != -1 { return dp[i as usize][s as usize]; } let ans; if (i as usize) == cost.len() { ans = i32::MAX; } else { let p1 = process2(cost, time, i + 1, s, dp); let mut p2 = i32::MAX; let next2 = process2(cost, time, i + 1, s - 1 - time[i as usize], dp); if next2 != i32::MAX { p2 = cost[i as usize] + next2; } ans = p1.min(p2); } dp[i as usize][s as usize] = ans; ans } fn paint_walls3(cost: Vec<i32>, time: Vec<i32>) -> i32 { let n = cost.len(); let mut dp = vec![i32::MAX; n + 1]; dp[0] = 0; for i in (0..n).rev() { for s in (1..=n as i32).rev() { if s - 1 - time[i] <= 0 { dp[s as usize] = dp[s as usize].min(cost[i]); } else if dp[(s - 1 - time[i]) as usize] != i32::MAX { dp[s as usize] = dp[s as usize].min(cost[i] + dp[(s - 1 - time[i]) as usize]); } } } dp[n] } fn main() { let cost = vec![1, 2, 3, 2]; let time = vec![1, 2, 3, 2]; let result1 = paint_walls1(cost.clone(), time.clone()); let result2 = paint_walls2(cost.clone(), time.clone()); let result3 = paint_walls3(cost.clone(), time.clone()); println!("Result for paint_walls1: {}", result1); println!("Result for paint_walls2: {}", result2); println!("Result for paint_walls3: {}", result3); }
#include <iostream> #include <vector> #include <algorithm> using namespace std; // 暴力递归 int process1(vector<int>& cost, vector<int>& time, int i, int s) { if (s <= 0) { return 0; } if (i == cost.size()) { return INT_MAX; } else { int p1 = process1(cost, time, i + 1, s); int p2 = INT_MAX; int next2 = process1(cost, time, i + 1, s - 1 - time[i]); if (next2 != INT_MAX) { p2 = cost[i] + next2; } return min(p1, p2); } } int paintWalls1(vector<int>& cost, vector<int>& time) { return process1(cost, time, 0, cost.size()); } // 暴力递归改记忆化搜索 int process2(vector<int>& cost, vector<int>& time, int i, int s, vector<vector<int>>& dp) { if (s <= 0) { return 0; } if (dp[i][s] != -1) { return dp[i][s]; } int ans; if (i == cost.size()) { ans = INT_MAX; } else { int p1 = process2(cost, time, i + 1, s, dp); int p2 = INT_MAX; int next2 = process2(cost, time, i + 1, s - 1 - time[i], dp); if (next2 != INT_MAX) { p2 = cost[i] + next2; } ans = min(p1, p2); } dp[i][s] = ans; return ans; } int paintWalls2(vector<int>& cost, vector<int>& time) { int n = cost.size(); vector<vector<int>> dp(n + 1, vector<int>(n + 1, -1)); return process2(cost, time, 0, n, dp); } // 严格位置依赖的动态规划 + 空间压缩 int paintWalls3(vector<int>& cost, vector<int>& time) { int n = cost.size(); vector<int> dp(n + 1, INT_MAX); dp[0] = 0; for (int i = n - 1; i >= 0; i--) { for (int s = n; s >= 1; s--) { if (s - 1 - time[i] <= 0) { dp[s] = min(dp[s], cost[i]); } else if (dp[s - 1 - time[i]] != INT_MAX) { dp[s] = min(dp[s], cost[i] + dp[s - 1 - time[i]]); } } } return dp[n]; } int main() { vector<int> cost = { 1, 2, 3, 2 }; vector<int> time = { 1, 2, 3, 2 }; cout << "Result for paintWalls1: " << paintWalls1(cost, time) << endl; cout << "Result for paintWalls2: " << paintWalls2(cost, time) << endl; cout << "Result for paintWalls3: " << paintWalls3(cost, time) << endl; return 0; }
#include <stdio.h> #include <stdlib.h> #include <limits.h> int process1(int* cost, int* time, int i, int s, int costSize); int paintWalls1(int* cost, int costSize, int* time, int timeSize) { return process1(cost, time, 0, costSize, costSize); } int process1(int* cost, int* time, int i, int s, int costSize) { if (s <= 0) { return 0; } if (i == costSize) { return INT_MAX; } else { int p1 = process1(cost, time, i + 1, s, costSize); int p2 = INT_MAX; int next2 = process1(cost, time, i + 1, s - 1 - time[i], costSize); if (next2 != INT_MAX) { p2 = cost[i] + next2; } return (p1 < p2) ? p1 : p2; } } int process2(int* cost, int* time, int i, int s, int costSize, int** dp); int paintWalls2(int* cost, int costSize, int* time, int timeSize) { int** dp = (int**)malloc((costSize + 1) * sizeof(int*)); for (int i = 0; i <= costSize; i++) { dp[i] = (int*)malloc((costSize + 1) * sizeof(int)); for (int j = 0; j <= costSize; j++) { dp[i][j] = -1; } } int result = process2(cost, time, 0, costSize, costSize, dp); for (int i = 0; i <= costSize; i++) { free(dp[i]); } free(dp); return result; } int process2(int* cost, int* time, int i, int s, int costSize, int** dp) { if (s <= 0) { return 0; } if (dp[i][s] != -1) { return dp[i][s]; } int ans; if (i == costSize) { ans = INT_MAX; } else { int p1 = process2(cost, time, i + 1, s, costSize, dp); int p2 = INT_MAX; int next2 = process2(cost, time, i + 1, s - 1 - time[i], costSize, dp); if (next2 != INT_MAX) { p2 = cost[i] + next2; } ans = (p1 < p2) ? p1 : p2; } dp[i][s] = ans; return ans; } int paintWalls3(int* cost, int costSize, int* time, int timeSize); int paintWalls3(int* cost, int costSize, int* time, int timeSize) { int* dp = (int*)malloc((costSize + 1) * sizeof(int)); for (int i = 0; i <= costSize; i++) { dp[i] = INT_MAX; } dp[0] = 0; for (int i = costSize - 1; i >= 0; i--) { for (int s = costSize; s >= 1; s--) { if (s - 1 - time[i] <= 0) { dp[s] = (dp[s] < cost[i]) ? dp[s] : cost[i]; } else if (dp[s - 1 - time[i]] != INT_MAX) { dp[s] = (dp[s] < cost[i] + dp[s - 1 - time[i]]) ? dp[s] : cost[i] + dp[s - 1 - time[i]]; } } } int result = dp[costSize]; free(dp); return result; } int main() { int cost[] = { 1, 2, 3, 2 }; int time[] = { 1, 2, 3, 2 }; int result1 = paintWalls1(cost, 4, time, 4); printf("Result of paintWalls1: %d\n", result1); int result2 = paintWalls2(cost, 4, time, 4); printf("Result of paintWalls2: %d\n", result2); int result3 = paintWalls3(cost, 4, time, 4); printf("Result of paintWalls3: %d\n", result3); return 0; }