LintCode 解题记录17.10.21
来源:互联网 发布:汽车维修入库软件 编辑:程序博客网 时间:2024/05/21 11:26
前言
刷题的进度还是非常慢的,照这个进度,115道题估计过年前都刷不完。。真的是怠惰啊。
House Robber
题目描述
给定一个数组,要求每次不能取相邻的两个数,求能取到所有数的最大和。
思路
初读一遍,发现是最优化问题(最大化),于是就思考最优化的两种思路 贪心和Dp。这里采用Dp的思想。我自己的思路就是采用 局部最优化与全局最优化的思想。设local[i]表示抢了第i家所能获得的最大利润,global[i]表示到第i家时所能获得的最大利润。那么递归关系如下:
local[i] = num[i] + global[i-2]; (1)
global[i] = max{local[i], global[i-1]}; (2)
写出这个递推式的思路如下:
1.针对local[i],假设我抢了第i家,那么第i-1家就不能抢,此时所能获得的最大利润就是抢劫前i-2家所能获得的最大利润加上第i家的利润,于是就得到式1
2.针对global[i],就可以分为两种情况,抢劫第i家和没有抢劫第i家,如果抢劫了第i家,所能获得的最大利润就是local[i],如果没有抢劫第i家,那么所能所得的最大利润就是抢劫了前i-1家所能获得的最大利润。
综合一下,得到下面的递推关系:
global[i] = max(global[i-2]+num[i], global[i-1]),我们只要初始化global[0],global[1]就好了,其中global[0] = num[0], global[1] = max(num[0], num[1]);
挑战
O(n)时间复杂度,O(1)空间复杂度。
显然上面的思路是O(n)的时间复杂度,O(n)的空间复杂度,接下来就是优化空间复杂度。于是我维护3个变量分别代表global[i],global[i-1],global[i-2]即可。然后只需要顺序遍历即可。
代码
long long houseRobber(vector<int> &A) { // write your code here if (A.size() == 0) return 0; if (A.size() == 1) return A[0]; long long res = 0, before = A[0], pre = max(A[0], A[1]); //res = global[i], pre = global[i-1], before = global[i-2]; for (int i = 2; i < A.size(); i++) { res = max(before + A[i], pre); //i即将++,更新before与pre before = pre; pre = res; } return res; }
House Robber II
题目描述
还是这个小偷,现在是这个数组首尾相连,问你最大的偷取价值。
思路
其实这题就是上一题稍微变形一下,即如果偷了第一家,那么就不能偷最后一家;如果偷了最后一家,那么就不能偷第一家,实际上这道题只需要用两次House Robber中的方法,最后返回两者中的较大值即可。
代码
int houseRobber2(vector<int> nums) { // write your code here if (nums.size() == 0) return 0; if (nums.size() == 1) return nums[0]; //houseRobber即为上一道题的方法 int a = houseRobber(vector<int>(nums.begin(), nums.end()-1)); int b = houseRobber(vector<int>(nums.begin()+1, nums.end())); return max(a, b); }
House RobberIII
题目描述
现在这片房子既不是用数组表示,也不是用圆圈表示,而是用了一颗二叉树来表示。不能直接抢劫两个直接相连的房子,仍然返回这个最大的利润值。
思路
树的题目自然是递归来做。此题中,对于某一节点,显然是分是否抢劫该节点两种情况来进行讨论。如果是对于两种情况分别进行递归,那恐怕会获得超时错误。因为你相当于搜索了这棵树两遍。为了避免这种情况,用一个长度为2的数组来进行存储数据,res[0]表示没有抢劫该节点,而res[1]表示抢劫了该节点。那么对于某一节点,首先递归计算其左子树得到left数组,然后递归计算右子树得到right,那么于是有
res[0] = max(left[0], left[1]) + max(right[0], right[1]) ; //没有抢劫该节点
res[1] = left[0] + right[0] + node->val; //抢劫了该节点
代码
int houseRobber3(TreeNode * root) { // write your code here vector<int> res = helper(root); return max(res[0], res[1]); } vector<int> helper(TreeNode *node) { if (node == NULL) return vector<int>(2, 0); vector<int> left = helper(node->left); vector<int> right = helper(node->right); vector<int> res(2, 0); res[0] = max(left[0], left[1]) + max(right[0], right[1]); res[1] = left[0] + right[0] + node->val; return res; }
Unique Binary Search Trees II
题目描述
给定一个n,产生所有不同的二叉搜索树,每一颗树都存储着1-n这n个数。
思路
递归。对于一个范围[start, end],从中任远一个作为根节点,然后把该范围划分成了左右两个数组。然后用左边的数组递归得到其左子树集合,以及同样的右子树集合。最后对于左子树集合中的每一个节点,与右子树集合中的每一个节点,拼接成一棵树,并把该数的根节点放入最终的答案中。
代码
vector<TreeNode *> generateTrees(int n) { // write your code here if (n < 0) { return vector<TreeNode*> {NULL}; } return helper(1, n); } vector<TreeNode *> helper(int start, int end) { vector<TreeNode *> res; if (start > end) { res.push_back(NULL); return res; } for (int i = start; i <= end; i++) { vector<TreeNode *> left = helper(start, i-1); vector<TreeNode *> right = helper(i+1, end); for (auto l: left) { for (auto r: right) { TreeNode *root = new TreeNode(i); root->right = r; root->left = l; res.push_back(root); } } } return res; }
注意
这道题可以说是非常能体现树、递归、以及二元查找树的紧密联系了。题目挺经典的。
K SumII
题目描述
给定了n个数,从中选取k个数,使他们的和为target。
思路
dfs。注意一下递归终止的条件。
代码
vector<vector<int>> kSumII(vector<int> &A, int k, int target) { // write your code here vector<vector<int>> res; vector<int> tmp; dfs(res, tmp, A, k, target, 0); return res; } void dfs(vector<vector<int>> &res, vector<int> tmp, vector<int> A, int k, int target, int idx) { if (target <= 0 || k <= 0) { if (target == 0 && k == 0) { res.push_back(tmp); } return; } for (int i = idx; i < A.size(); i++) { tmp.push_back(A[i]); dfs(res, tmp, A, k-1, target-A[i], i+1); tmp.pop_back(); } }
- LintCode 解题记录17.10.21
- LintCode 解题记录 17.10.5 递归
- LintCode 解题记录 17.10.14 拓扑排序
- LintCode 解题记录17.4.27
- LintCode解题记录17.4.28
- LintCode解题记录 17.5.3
- LintCode 解题记录 2017.6.3
- LintCode 解题记录 7.11 ~ 7.16
- LintCode 解题记录 Matrix专题
- LintCode解题记录17.9.9
- LintCode解题记录-Catalan Number
- LintCode 解题记录 17.11.11
- LintCode 解题记录 17.5.15 (tag: 哈希表)
- LintCode 解题记录 17.5.22 (tag: Array)
- LintCode 解题记录 Array 17.6.5
- LintCode 解题记录 17.6.19~17.6.25
- LintCode 解题记录17.6.26 ~ 17.7.2
- LintCode 解题记录 17.8.30 两个指针
- parentNode明明有却返回null
- JDK7中ThreadPoolExecutor源码概述
- python 爬虫模拟登陆
- 教你认识各种分辨率的英文缩写
- C++之hello world
- LintCode 解题记录17.10.21
- Nginx
- iTextSharp
- 一元线性回归预测法
- C++ 指针调用
- C语言:字符串函数的实现
- 协同分割co-segmentation
- PY-append,time,print,datetime用法
- MyBatis框架的工作原理