动态规划法:
思路:
(1)状态定义:dp[i]代表前i家能偷盗的最大金额
(2)状态初始化:如果只有一家,只能偷这家dp[0]=nums[0];如果有两家,因为是连通的,所以,只能偷较富的dp[i]=max(nums[1],nums[0])
(3)状态转移:如果大于等于3家,转移方程为:dp[i]=max(dp[i-1],dp[i-2]+nums[i])
class Solution
{
public:int rob(vector<int>& nums){int n = nums.size();vector<int> dp;dp.resize(n);if(n==1) return nums[0];else if(n==2) return max(nums[0],nums[1]);else{// 状态初始化dp[0] = nums[0];dp[1] = max(nums[0], nums[1]);for(int i = 2; i<n; i++){// 状态转移dp[i] = max(dp[i-1], dp[i-2] + nums[i]);}return dp[n-1];}}
};
解法二、奇偶性
思路:
设置两个变量,sumOdd 和 sumEven 分别对数组的奇数和偶数元素求和。
遍历数组,索引为奇数时,将元素加到奇数和,并与偶数和比较更新成max。
偶数和同理。
返回时进行最后一次更新max。
class solution
{
public:int rob(vector<int>& nums){int sumOdd = 0; // 奇数和int sumEven = 0; // 偶数和for(int i = 0; i<nums.size(); i++){if(i%2 == 0){sumEven += nums[i];sumEven = max(sumEven,sumOdd);}else{sumOdd += nums[i];sumOdd = max(sumEven,sumOdd);}}return max(sumOdd,sumEven);}
};
动态规划法:
思路:
保存当前的最大值和最小值
所有最大值中最大的那个就是结果
状态定义:
dpmin[i] = 以i下标结尾的最小乘积
dpmax[i] = 以i下标结尾的最大乘积;
状态初始化:
状态转移方程:
1、nums[i] = 0
dpmin[i] = dpmax[i] = 0
2、nums[i] > 0
dpmax[i] = max(dpmax[i - 1] * nums[i], nums[i])
dpmin[i] = min(dpmin[i - 1] * nums[i], nums[i])
正数 * 较大值->较大值,正数 * 较小值->较小值
nums[i]要么续上之前的min或max,要么不续上,自己就是当前最大值或者最小值
3、nums[i] < 0
dpmax[i] = max(dpmin[i-1] * nums[i], nums[i])
dpmin[i] = min(dpmax[i-1] * nums[i], nums[i])
负数 * 较大值->较小值,负数 * 较小值->较大值
nums[i]要么续上之前的min或max,要么不续上,自己就是当前最大值或者最小值。
result = max(dpmax[i])
class Solution
{
public:int maxProduct(vector<int> &nums){int n = nums.size();// 数组中至少存在一个数,所以nums[0]存在// dpmin[0] = dpmax[0] = nums[0]int dpmin = nums[0], dpmax = nums[0];// result=max(dpmax[i]), 这里先令result = dpmax[0]int res = dpmax;for(int i = 1; i < n; i++){if(nums[i] == 0){dpmin = dpmax = 0;}else if(nums[i] > 0){dpmax = max(dpmax * nums[i], nums[i]);dpmin = min(dpmin * nums[i], nums[i]);}else{// tmp用来临时保存dpmaxint tmp = dpmax;dpmax = max(dpmin * nums[i], nums[i]);dpmin = min(tmp * nums[i], nums[i]);}res = max(res, dpmax);}return res;}
};