代码随想录算法训练营第三十六天| 198.打家劫舍 213.打家劫舍II 337.打家劫舍III
198.打家劫舍
要求:
给定一个nums,要求取得最大值,但是不可以选择两个相邻的数
dp定义:
dp[n],取到第N个数字的时候,最大值
递推公式:
取:nums[i] + dp[j-2]
不取: nums[i-1];
代码:
1 // 在两个数字不相邻的情况下,得到的最大金额 2 // 思路: 3 // dp[n] 第N个数字时的最大金额数 4 // 难点: 5 // 1,如何做到全局最大 4 7 9 1 6 // 2,中间还可能不相隔 2 1 1 2 7 // 8 // dp[j] 取,不取 9 // dp[j-1] , value[i]+dp[j-2];. 10 // 11 // 初始化?因为第0个也不一定被拿到 12 // 13 // 根据定义:dp[0] = nums[0] dp[1] = max 14 // 15 // 如何巧妙的可以用到之前的数值,同时不固定必须的选择顺序, 16 // dp = max(dp[j-1], nums[1]+dp[j-2]) 17 // 18 int rob(vector<int>& nums) { 19 if (nums.size() == 1)return nums[0]; 20 21 vector<int>dp(nums.size(), 0); 22 dp[0] = nums[0]; 23 dp[1] = max(nums[0], nums[1]); 24 25 for (int i = 2; i < nums.size(); i++) 26 { 27 dp[i] = max(dp[i - 1], nums[i] + dp[i - 2]); 28 } 29 30 return dp[nums.size() - 1]; 31 }
213.打家劫舍II
要求:
首尾是相连的,如何在环里面找到最大值?
难点:
.哪个点作为初始化,第0个,不可能直接取,因为和尾部有关联
思路:
分成多步,拆成线性的:
1,取头
2,取尾
代码:
1 // 要求:这些数字是环形,在不相邻的情况下,得到最大值 2 // dp[n] 第N个数字时,最大的金钱数 3 // 难点: 4 // 1,初始化的时候第0个 如何初始化 5 // 需要总结,如何破环 6 // 7 // 如何破环: 8 // 把问题分成多步进行思考:取头,取尾 9 // 10 int rob(vector<int>& nums) { 11 if (nums.size() == 1) return nums[0]; 12 if (nums.size() == 2) return max(nums[0], nums[1]); 13 vector<int> head(nums.begin(), nums.end() - 1); 14 vector<int> tail(nums.begin() + 1, nums.end()); 15 16 int reuslt1 = 0, result2 = 0; 17 18 vector<int> dp1(head.size(), 0), dp2(tail.size(), 0); 19 dp1[0] = nums[0]; 20 dp1[1] = max(nums[0], nums[1]); 21 22 dp2[0] = nums[1]; 23 dp2[1] = max(nums[2], nums[1]); 24 25 for (int i = 2; i < nums.size(); i++) 26 { 27 if (i != nums.size() - 1) 28 { 29 dp1[i] = max(dp1[i - 1], nums[i] + dp1[i - 2]); 30 } 31 32 if (i >= 3) 33 { 34 dp2[i-1] = max(dp2[i - 2], nums[i] + dp2[i - 3]); 35 } 36 } 37 38 return max(dp1[nums.size() - 2], dp2[nums.size() - 2]); 39 }
337.打家劫舍III
难点:
存在表亲的关系,不可以直接用层序遍历进行简化:2 1 3 null 4
思路:
两个状态,一个是取,另一个是不取
// f[0] = max(left[0],left[1])+max(right[0],right[1])
// f[1] = nums + left[0]+right[0];
代码:
1 // 要求L: 父子节点之间不可以相邻,取最大值 2 // 层序遍历 3 // 4 // 正确思路:f[0] 表示不选时的最大值 f[1]表示选的时候的最大值 5 // 6 // f[0] = max(left[0],left[1])+max(right[0],right[1]) 7 // f[1] = nums + left[0]+right[0]; 8 // 9 10 vector<int> rob_cursor(TreeNode* node) 11 { 12 if (!node) return vector<int>{0, 0}; 13 14 vector<int> left_ = { 0,0 }, right_ = { 0, 0 }, result = { 0,0 }; 15 16 if (node->left) left_ = rob_cursor(node->left); 17 if (node->right) right_ = rob_cursor(node->right); 18 19 result[0] = max(left_[0],left_[1]) + max(right_[0],right_[1]); 20 result[1] = node->val + left_[0] + right_[0]; 21 22 return result; 23 } 24 25 26 int rob(TreeNode* root) { 27 auto result = rob_cursor(root); 28 29 return max(result[0], result[1]); 30 }