t2:2320. 统计放置房子的方式数 - 力扣(LeetCode)
分析题目,发现街道的两边是没有互相影响的,所以只要求出街道一边的放置方案数n,然后答案就是。
那怎么求一边的方案数呢?
一开始我用的是dfs,看能不能运气好过了。答案当然是喜提一个"超时"
于是开始思考:明显dfs是不行的,那只能从O(n)时间复杂度的方向想了,一般来说常见思路就是:从已知的结果中推出未知的结果,其实就是“动态规划”的思想。假设知道f(n-1)表示n-1的方案数,那么如何求出f(n)呢???
很明显有两种情况需要讨论【先固定最后的n,类似于背包问题】:
- 如果第
n个位置有房子,那么第n-1个位置就不能放房子,此时f(n)=f(n-2) - 如果第
n个位置没有房子,那么第n-1个位置可以选择放或者不放房子,此时f(n)=f(n-1)
因此f(n) = f(n-1) + f(n-2),就是个斐波拉契数列。
另外要注意下乘法要用long来接。本人比赛提交的代码:
class Solution {
private int mod = 1000000007;
public int countHousePlacements(int n) {
int[] f = new int[10001];
f[1] = 2;
f[2] = 3;
for (int i = 3; i <= n; i++) {
f[i] = (f[i - 1] % mod + f[i - 2] % mod) % mod;
}
long mod_ = (int)((f[n]) % mod);
long tmpR = mod_ * mod_;
int result = (int)(tmpR % mod);
return result;
}
}
t3: 2321. 拼接数组的最大分数 - 力扣(LeetCode)
假设数组1的和为,数组2的和为,数组1,2分别叫X,,Y。
并且交换的最大分数对应的下标范围是i~j,于是交换后数组1的和表达式为:,
同理,交换后的数组2的和表达式为:
于是最终的结果就是
因为是常数,所以问题变为求解:
观察到这里的和对应着同一段范围,上述两式可转变为:和
于是可以将数组减去数组,得到数组
所以只要求出的最大连续子数组和就行
同理,可以将数组减去数组,得到数组
所以只要求出的最大连续子数组和就行
比赛时通过的代码:
补充下求最大子数组用一个变量就行
public int maximumsSplicedArray(int[] nums1, int[] nums2) {
int n = nums1.length;
int[] Y_X = new int[n];
int[] X_Y = new int[n];
int sum1 = 0, sum2 = 0;
for (int i = 0; i < n; i++) {
sum1 += nums1[i];
sum2 += nums2[i];
Y_X[i] = nums2[i] - nums1[i];
X_Y[i] = nums1[i] - nums2[i];
}
int maxY_X = Y_X[0];
int maxX_Y = X_Y[0];
int[] dY_X = new int[n];
int[] dX_Y = new int[n];
dY_X[0] = Y_X[0];
dX_Y[0] = X_Y[0];
for (int i = 1; i < n; i++) {
if (dY_X[i - 1] < 0) {
dY_X[i] = Y_X[i];
} else {
dY_X[i] = Y_X[i] + dY_X[i - 1];
}
maxY_X = Math.max(maxY_X, dY_X[i]);
if (dX_Y[i - 1] < 0) {
dX_Y[i] = X_Y[i];
} else {
dX_Y[i] = X_Y[i] + dX_Y[i - 1];
}
maxX_Y = Math.max(maxX_Y, dX_Y[i]);
}
int maxSum1 = sum1 + maxY_X;
int maxSum2 = sum2 + maxX_Y;
return Math.max(maxSum1, maxSum2);
}