楼主: zhuli19901106
跳转到指定楼层
上一主题 下一主题
收起左侧

分享我的Lintcode题解,目前进度244/248

 
🔗
 楼主| zhuli19901106 2015-7-22 20:44:27 | 只看该作者
全局:
Sort Colors
题意:给定一个只包含0,1,2的数组,用线性时间排序。
解法1:数数。
代码1:
  1. class Solution{
  2. public:
  3.     /**
  4.      * @param nums: A list of integer which is 0, 1 or 2
  5.      * @return: nothing
  6.      */   
  7.     void sortColors(vector<int> &nums) {
  8.         auto &a = nums;
  9.         int n = a.size();
  10.         vector<int> c(3, 0);
  11.         int i;
  12.         for (i = 0; i < n; ++i) {
  13.             ++c[a[i]];
  14.         }
  15.         int j, k = 0;
  16.         for (i = 0; i < 3; ++i) {
  17.             for (j = 0; j < c[i]; ++j) {
  18.                 a[k++] = i;
  19.             }
  20.         }
  21.     }
  22. };
复制代码
复杂度1:时间O(N),空间O(1)。

解法2:题目要求one-pass,O(1)空间。于是我想了一下就有了下面这个思路,但是真的写起代码来才发现bug不少,调了半天才搞对。
代码2:
  1. // How tricky...
  2. // It took me over 20 minutes to put it right.
  3. #include <algorithm>
  4. using namespace std;

  5. class Solution{
  6. public:
  7.     /**
  8.      * @param nums: A list of integer which is 0, 1 or 2
  9.      * @return: nothing
  10.      */   
  11.     void sortColors(vector<int> &nums) {
  12.         auto &a = nums;
  13.         int n = a.size();
  14.         int i, j;
  15.         int ii, jj;
  16.         ii = i = 0;
  17.         jj = j = n - 1;
  18.         while (i < j) {
  19.             if (a[i] == 0) {
  20.                 swap(a[i], a[ii]);
  21.                 ++ii;
  22.                 i = max(i, ii);
  23.             } else if (a[j] == 2) {
  24.                 swap(a[j], a[jj]);
  25.                 --jj;
  26.                 j = min(j, jj);
  27.             } else if (a[i] == 2) {
  28.                 swap(a[i], a[jj]);
  29.                 --jj;
  30.                 j = min(j, jj);
  31.             } else if (a[j] == 0) {
  32.                 swap(a[j], a[ii]);
  33.                 ++ii;
  34.                 i = max(i, ii);
  35.             } else {
  36.                 ++i;
  37.             }
  38.         }
  39.         while (ii <= jj) {
  40.             a[ii++] = 1;
  41.         }
  42.     }
  43. };
复制代码
复杂度2:时间O(N),空间O(1)。
回复

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-22 20:49:42 | 只看该作者
全局:
Best Time to Buy and Sell Stock
题意:给定股价,允许你至多买卖一次,求最大获利。
解法:不断更新最低价,不断更新最大获利。
代码:
  1. class Solution {
  2. public:
  3.     /**
  4.      * @param prices: Given an integer array
  5.      * @return: Maximum profit
  6.      */
  7.     int maxProfit(vector<int> &prices) {
  8.         int n = prices.size();
  9.         if (n == 0) {
  10.             return 0;
  11.         }
  12.         int minVal = prices[0];
  13.         int ans = 0;
  14.         int i;
  15.         for (i = 1; i < n; ++i) {
  16.             minVal = min(minVal, prices[i]);
  17.             ans = max(ans, prices[i] - minVal);
  18.         }
  19.         return ans;
  20.     }
  21. };
复制代码
复杂度:时间O(N),空间O(1)。
回复

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-22 21:13:54 | 只看该作者
全局:
Best Time to Buy and Sell Stock II
题意:给定股价,允许你买卖无数次,但手里不能同时有两笔交易进行。求最大收益。
解法:只要涨价就买。现实中哪有这好事。
代码:
  1. class Solution {
  2. public:
  3.     /**
  4.      * @param prices: Given an integer array
  5.      * @return: Maximum profit
  6.      */
  7.     int maxProfit(vector<int> &prices) {
  8.         int sum = 0;
  9.         int n = prices.size();
  10.         int i;
  11.         for (i = 0; i < n - 1; ++i) {
  12.             if (prices[i + 1] > prices[i]) {
  13.                 sum += prices[i + 1] - prices[i];
  14.             }
  15.         }
  16.         return sum;
  17.     }
  18. };
复制代码
复杂度:时间O(N),空间O(1)。
回复

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-22 21:30:59 | 只看该作者
全局:
Best Time to Buy and Sell Stock III
题意:给定股价,允许你至多进行两次交易,并且不能同时进行。求最大收益。
解法:从左向右算一次,从右向左算一次。拼起来就是最大收益。
代码:
  1. // O(n) time and O(n) space
  2. #include <algorithm>
  3. using namespace std;

  4. class Solution {
  5. public:
  6.     /**
  7.      * @param prices: Given an integer array
  8.      * @return: Maximum profit
  9.      */
  10.     int maxProfit(vector<int> &prices) {
  11.         auto &a = prices;
  12.         int n = a.size();
  13.         if (n == 0) {
  14.             return 0;
  15.         }
  16.         int i;
  17.         vector<int> dl;
  18.         dl.resize(n);
  19.         dl[0] = a[0];
  20.         for (i = 1; i < n; ++i) {
  21.             dl[i] = min(dl[i - 1], a[i]);
  22.         }
  23.         dl[0] = 0;
  24.         for (i = 1; i < n; ++i) {
  25.             dl[i] = max(dl[i - 1], a[i] - dl[i]);
  26.         }
  27.         int ans = dl[n - 1];
  28.         int maxVal = a[n - 1];
  29.         for (i = n - 2; i >= 0; --i) {
  30.             maxVal = max(maxVal, a[i]);
  31.             ans = max(ans, maxVal - a[i] + dl[i]);
  32.         }
  33.         return ans;
  34.     }
  35. };
复制代码
复杂度:时间O(N),空间O(1)。
回复

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-22 21:47:30 | 只看该作者
全局:
Combinations
题意:从1-N选出K个数,求所有组合。
解法:DFS。
代码:
  1. class Solution {
  2. public:
  3.     /**
  4.      * @param n: Given the range of numbers
  5.      * @param k: Given the numbers of combinations
  6.      * @return: All the combinations of k numbers out of 1..n
  7.      */
  8.     vector<vector<int> > combine(int n, int k) {
  9.         ans.clear();
  10.         v.clear();
  11.         this->n = n;
  12.         this->k = k;
  13.         DFS(1, 0);
  14.         return ans;
  15.     }
  16. private:
  17.     vector<vector<int> > ans;
  18.     vector<int> v;
  19.     int n, k;
  20.    
  21.     void DFS(int idx, int cc) {
  22.         if (cc == k) {
  23.             ans.push_back(v);
  24.             return;
  25.         }
  26.         
  27.         int i;
  28.         for (i = idx; i <= cc + n - k + 1; ++i) {
  29.             v.push_back(i);
  30.             DFS(i + 1, cc + 1);
  31.             v.pop_back();
  32.         }
  33.     }
  34. };
复制代码
复杂度:时间O(C(N,K)),空间一样。
回复

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-22 21:53:36 | 只看该作者
全局:
本帖最后由 zhuli19901106 于 2015-7-22 21:54 编辑

Combination Sum II
题意:给定一个正整数数组,求其中所有加起来等于T的组合,数组中每个元素至多用一次。结果中不能包含重复组合。
解法:先数个数。然后DFS,注意剪枝。
代码:
  1. #include <map>
  2. using namespace std;

  3. class Solution {
  4. public:
  5.     /**
  6.      * @param num: Given the candidate numbers
  7.      * @param target: Given the target number
  8.      * @return: All the combinations that sum to target
  9.      */
  10.     vector<vector<int> > combinationSum2(vector<int> &num, int target) {
  11.         v.clear();
  12.         a.clear();
  13.         c.clear();
  14.         ans.clear();
  15.         
  16.         n = num.size();
  17.         if (n == 0) {
  18.             return ans;
  19.         }
  20.         map<int, int> mm;
  21.         int i;
  22.         for (i = 0; i < n; ++i) {
  23.             ++mm[num[i]];
  24.         }
  25.         for (auto it = mm.begin(); it != mm.end(); ++it) {
  26.             a.push_back(it->first);
  27.             c.push_back(it->second);
  28.         }
  29.         n = a.size();
  30.         t = target;
  31.         DFS(0, 0);
  32.         return ans;
  33.     }
  34. private:
  35.     vector<int> a, c;
  36.     vector<int> v;
  37.     int n;
  38.     int t;
  39.     vector<vector<int> > ans;
  40.    
  41.     void DFS(int idx, int sum) {
  42.         if (sum == t) {
  43.             ans.push_back(v);
  44.             return;
  45.         }
  46.         if (idx == n) {
  47.             return;
  48.         }
  49.         int i, j;
  50.         for (i = 0; i <= c[idx]; ++i) {
  51.             if (sum + i * a[idx] > t) {
  52.                 break;
  53.             }
  54.             for (j = 0; j < i; ++j) {
  55.                 v.push_back(a[idx]);
  56.             }
  57.             DFS(idx + 1, sum + i * a[idx]);
  58.             for (j = 0; j < i; ++j) {
  59.                 v.pop_back();
  60.             }
  61.         }
  62.     }
  63. };
复制代码
复杂度:时间O(N!),空间一样。
回复

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-22 22:15:01 | 只看该作者
全局:
Regular Expression Matching
题意:hard难度。实现正则表达式中的‘.’和‘*’元字符。
解法:真是名副其实的难题,第一次碰见这题时可以说毫无思路,后来搜答案连答案都没看懂。对比了好几个人的解法,才明白关键的地方在于“回溯”。比如.*可以匹配任意字串,那么某个位置匹配不下去了,我们就找到最近的一个*,看看能不能让*多覆盖一个字符,然后回溯到被覆盖的字符的下一位,继续往前。这就好比DFS+回溯的思路,只不过形式用的是循环,而不是递归。当然,此方法效率并不算高,因为每次只是多覆盖一位。要更优化的算法,感觉需要学好编译原理才行了。目前我还不会NFA。
代码:
  1. #include <cstring>
  2. #include <vector>
  3. using namespace std;

  4. class Solution {
  5. public:
  6.     /**
  7.      * @param s: A string
  8.      * @param p: A string includes "." and "*"
  9.      * @return: A boolean
  10.      */
  11.     bool isMatch(const char *s, const char *p) {
  12.         if (s == NULL || p == NULL) {
  13.             return false;
  14.         }
  15.         int ls = strlen(s);
  16.         int lp = strlen(p);
  17.         if (lp == 0) {
  18.             return ls == 0;
  19.         }
  20.         
  21.         int i;
  22.         for (i = 0; i < lp - 1; ++i) {
  23.             if (p[i] == '*' && (i == 0 || p[i + 1] == '*')) {
  24.                 // Invalid pattern
  25.                 return false;
  26.             }
  27.         }
  28.         
  29.         vector<int> ai, aj;
  30.         int j;
  31.         
  32.         i = j = 0;
  33.         while (i < ls) {
  34.             if (j + 1 < lp && p[j + 1] == '*') {
  35.                 ai.push_back(i);
  36.                 aj.push_back(j);
  37.                 j += 2;
  38.             } else if (p[j] == '.' || s[i] == p[j]) {
  39.                 ++i;
  40.                 ++j;
  41.             } else if (!aj.empty()) {
  42.                 while (!aj.empty()) {
  43.                     if (p[aj.back()] == '.' || p[aj.back()] == s[ai.back()]) {
  44.                         i = ++ai.back();
  45.                         j = aj.back() + 2;
  46.                         break;
  47.                     }
  48.                     ai.pop_back();
  49.                     aj.pop_back();
  50.                 }
  51.             } else {
  52.                 return false;
  53.             }
  54.         }
  55.         while (j + 1 < lp && p[j + 1] == '*') {
  56.             j += 2;
  57.         }
  58.         return j == lp;
  59.     }
  60. };
复制代码
复杂度:如果有NS个*号,那么时间复杂度应该有O(N ^ NS),空间O(N)。
回复

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-22 22:21:43 | 只看该作者
全局:
Minimum Depth of Binary Tree
题意:给定一棵二叉树,求最浅的叶结点的深度。
解法:递归解决。注意递归的终止条件是叶结点
代码:
  1. #include <algorithm>
  2. #include <climits>
  3. using namespace std;
  4. /**
  5. * Definition of TreeNode:
  6. * class TreeNode {
  7. * public:
  8. *     int val;
  9. *     TreeNode *left, *right;
  10. *     TreeNode(int val) {
  11. *         this->val = val;
  12. *         this->left = this->right = NULL;
  13. *     }
  14. * }
  15. */
  16. class Solution {
  17. public:
  18.     /**
  19.      * @param root: The root of binary tree.
  20.      * @return: An integer
  21.      */
  22.     int minDepth(TreeNode *root) {
  23.         if (root == NULL) {
  24.                         return 0;
  25.                 }
  26.                 if (root->left == NULL && root->right == NULL) {
  27.                         return 1;
  28.                 }
  29.                 int ans = INT_MAX;
  30.                 if (root->left != NULL) {
  31.                         ans = min(ans, minDepth(root->left) + 1);
  32.                 }
  33.                 if (root->right != NULL) {
  34.                         ans = min(ans, minDepth(root->right) + 1);
  35.                 }
  36.                
  37.                 return ans;
  38.     }
  39. };
复制代码
复杂度:时间O(N),空间O(N)。
回复

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-22 22:26:03 | 只看该作者
全局:
Unique Characters
题意:求一个字符串中是否有重复字符。
解法1:统计个数。用位向量节省空间也可以,不过感觉这题玩出一堆花样也没什么意义。
代码1:
  1. #include <cstring>
  2. using namespace std;

  3. class Solution {
  4. public:
  5.     /**
  6.      * @param str: a string
  7.      * @return: a boolean
  8.      */
  9.     bool isUnique(string &str) {
  10.         char a[256];
  11.         memset(a, 0, sizeof(a));
  12.         int n = str.length();
  13.         int i;
  14.         for (i = 0; i < n; ++i) {
  15.             if (a[str[i]]) {
  16.                 return false;
  17.             }
  18.             a[str[i]] = 1;
  19.         }
  20.         return true;
  21.     }
  22. };
复制代码
复杂度1:时间O(N),空间O(1)。

解法2:排序,然后看相邻字符是否相等。
代码2:
  1. #include <algorithm>
  2. using namespace std;

  3. class Solution {
  4. public:
  5.     /**
  6.      * @param str: a string
  7.      * @return: a boolean
  8.      */
  9.     bool isUnique(string &str) {
  10.         sort(str.begin(), str.end());
  11.         int n = str.length();
  12.         int i;
  13.         for (i = 0; i < n - 1; ++i) {
  14.             if (str[i] == str[i + 1]) {
  15.                 return false;
  16.             }
  17.         }
  18.         return true;
  19.     }
  20. };
复制代码
复杂度2:时间O(N * log(N)),空间O(1)。
回复

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-22 22:47:43 | 只看该作者
全局:
Two Strings Are Anagrams
题意:求两个字符串的字符组成是否相同。
解法1:排序之后是否相等。
代码1:
  1. #include <algorithm>
  2. using namespace std;

  3. class Solution {
  4. public:
  5.         /**
  6.          * @param s: The first string
  7.          * @param b: The second string
  8.          * @return true or false
  9.          */
  10.         bool anagram(string s, string t) {
  11.                 // write your code here
  12.                 sort(s.begin(), s.end());
  13.                 sort(t.begin(), t.end());
  14.                 return s == t;
  15.         }
  16. };
复制代码
复杂度1:时间O(N * log(N)),空间O(1)。

解法2:数数。
代码2:
  1. #include <cstring>
  2. using namespace std;

  3. class Solution {
  4. public:
  5.         /**
  6.          * @param s: The first string
  7.          * @param b: The second string
  8.          * @return true or false
  9.          */
  10.         bool anagram(string s, string t) {
  11.         int c[256];
  12.         memset(c, 0, sizeof(c));
  13.         int len = s.length();
  14.         int i;
  15.         for (i = 0; i < len; ++i) {
  16.             ++c[s[i]];
  17.         }
  18.         len = t.length();
  19.         for (i = 0; i < len; ++i) {
  20.             --c[t[i]];
  21.         }
  22.         for (i = 0; i < 256; ++i) {
  23.             if (c[i]) {
  24.                 return false;
  25.             }
  26.         }
  27.                 return true;
  28.         }
  29. };
复制代码
复杂度2:时间O(N),空间O(1)。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册账号
隐私提醒:
  • ☑ 禁止发布广告,拉群,贴个人联系方式:找人请去🔗同学同事飞友,拉群请去🔗拉群结伴,广告请去🔗跳蚤市场,和 🔗租房广告|找室友
  • ☑ 论坛内容在发帖 30 分钟内可以编辑,过后则不能删帖。为防止被骚扰甚至人肉,不要公开留微信等联系方式,如有需求请以论坛私信方式发送。
  • ☑ 干货版块可免费使用 🔗超级匿名:面经(美国面经、中国面经、数科面经、PM面经),抖包袱(美国、中国)和录取汇报、定位选校版
  • ☑ 查阅全站 🔗各种匿名方法

本版积分规则

>
快速回复 返回顶部 返回列表