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

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

 
🔗
 楼主| zhuli19901106 2015-7-18 17:16:00 | 只看该作者
全局:
strStr
题意:实现strstr函数,也就是查找字符串s里是否出现了字符串t。考察字符串匹配。
解法1:暴力解法
代码1:
  1. // The brute-force solution.
  2. #include <cstring>
  3. using namespace std;

  4. class Solution {
  5. public:
  6.     /**
  7.      * Returns a index to the first occurrence of target in source,
  8.      * or -1  if target is not part of source.
  9.      * @param source string to be scanned.
  10.      * @param target string containing the sequence of characters to match.
  11.      */
  12.     int strStr(const char *source, const char *target) {
  13.         if (source == NULL || target == NULL) {
  14.             return -1;
  15.         }
  16.         int ls = strlen(source);
  17.         int lt = strlen(target);
  18.         
  19.         if (lt > ls) {
  20.             return -1;
  21.         }
  22.         
  23.         int i, j;
  24.         for (i = 0; i + lt <= ls; ++i) {
  25.             for (j = 0; j < lt; ++j) {
  26.                 if (source[i + j] != target[j]) {
  27.                     break;
  28.                 }
  29.             }
  30.             if (j == lt) {
  31.                 return i;
  32.             }
  33.         }
  34.         
  35.         return -1;
  36.     }
  37. };
复制代码
复杂度1:时间O(N * M),空间O(1)

解法2:神器名叫KMP。最好能理解next数组的思想,这才是KMP算法的巧妙之处。next数组还可以用来解相关的变形题目。比如这题
https://leetcode.com/problems/shortest-palindrome/
代码2:
  1. // The KMP solution.
  2. #include <cstring>
  3. using namespace std;

  4. class Solution {
  5. public:
  6.     /**
  7.      * Returns a index to the first occurrence of target in source,
  8.      * or -1  if target is not part of source.
  9.      * @param source string to be scanned.
  10.      * @param target string containing the sequence of characters to match.
  11.      */
  12.     int strStr(const char *source, const char *target) {
  13.         if (source == NULL || target == NULL) {
  14.             return -1;
  15.         }
  16.         if (target[0] == 0) {
  17.             return 0;
  18.         }
  19.         
  20.         ls = strlen(source);
  21.         lt = strlen(target);
  22.         s = source;
  23.         t = target;
  24.         
  25.         if (lt > ls) {
  26.             return -1;
  27.         }
  28.         
  29.         next = new int[lt + 1];
  30.         memset(next, 0, (lt + 1) * sizeof(int));
  31.         getNext();
  32.         
  33.         int ans = KMPMatch();
  34.         delete[] next;
  35.         
  36.         return ans;
  37.     }
  38. private:
  39.     int* next;
  40.     int ls;
  41.     int lt;
  42.     const char *s;
  43.     const char *t;
  44.    
  45.     void getNext() {
  46.         int i, j;
  47.         i = 0;
  48.         j = -1;
  49.         
  50.         next[0] = -1;
  51.         while (i < lt) {
  52.             if (j == -1 || t[i] == t[j]) {
  53.                 ++i;
  54.                 ++j;
  55.                 next[i] = j;
  56.             } else {
  57.                 j = next[j];
  58.             }
  59.         }
  60.     }
  61.    
  62.     int KMPMatch() {
  63.         int i, j;
  64.         
  65.         i = j = 0;
  66.         while (i < ls) {
  67.             if (j == -1 || s[i] == t[j]) {
  68.                 ++i;
  69.                 ++j;
  70.             } else {
  71.                 j = next[j];
  72.             }
  73.             if (j == lt) {
  74.                 return i - lt;
  75.             }
  76.         }
  77.         return -1;
  78.     }
  79. };
复制代码
复杂度2:O(N + M)时间,O(M)空间
回复

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-18 17:20:43 | 只看该作者
全局:
Binary Search
题意:在有序数组中二分搜索一个元素,要求返回此元素首次出现的位置。
解法:既然要求首次出现的位置,那么就得用lower_bound,此处还是推荐自己实现一个。
代码:
  1. class Solution {
  2. public:
  3.         /**
  4.          * @param nums: The integer array.
  5.          * @param target: Target number to find.
  6.          * @return: The first position of target. Position starts from 0.
  7.          */
  8.         int binarySearch(vector<int> &array, int target) {
  9.                 int n = array.size();
  10.                 if (target < array[0] || target > array[n - 1]) {
  11.                         return -1;
  12.                 }
  13.                 if (target == array[0]) {
  14.                         return 0;
  15.                 }
  16.                
  17.                 int ll, rr, mm;
  18.                 ll = 0;
  19.                 rr = n - 1;
  20.                 while (rr - ll > 1) {
  21.                         mm = (ll + rr) / 2;
  22.                         if (array[mm] < target) {
  23.                                 ll = mm;
  24.                         } else {
  25.                                 rr = mm;
  26.                         }
  27.                 }
  28.                
  29.                 return array[rr] == target ? rr : -1;
  30.         }
  31. };
复制代码
复杂度:时间O(log N),空间O(1)。
回复

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-18 17:27:49 | 只看该作者
全局:
Permutations
题意:给定一个数组,求可以构成的所有排列。按结果来看,数组中应该没有重复元素。
解法1:元素个数为N,则共有N!个排列。先排好序,然后调用N次next_permutatio即可。
代码1:
  1. // The iterative solution
  2. #include <algorithm>
  3. using namespace std;

  4. class Solution {
  5. public:
  6.     /**
  7.      * @param nums: A list of integers.
  8.      * @return: A list of permutations.
  9.      */
  10.     vector<vector<int> > permute(vector<int> nums) {
  11.         ans.clear();
  12.         int n = nums.size();
  13.         if (n == 0) {
  14.             return ans;
  15.         }
  16.         sort(nums.begin(), nums.end());
  17.         int f = 1;
  18.         int i;
  19.         for (i = 2; i <= n; ++i) {
  20.             f *= i;
  21.         }
  22.         for (i = 0; i < f; ++i) {
  23.             ans.push_back(nums);
  24.             next_permutation(nums.begin(), nums.end());
  25.         }
  26.         return ans;
  27.     }
  28. private:
  29.     vector<vector<int> > ans;
  30. };
复制代码
复杂度1:时间O(N * N!),空间O(1)

解法2:使用递归实现,既不方便,也不高效。只是为了试试递归怎么写才刻意写的。
代码2:
  1. // The recursive solution
  2. #include <algorithm>
  3. using namespace std;

  4. class Solution {
  5. public:
  6.     /**
  7.      * @param nums: A list of integers.
  8.      * @return: A list of permutations.
  9.      */
  10.     vector<vector<int> > permute(vector<int> nums) {
  11.         ans.clear();
  12.         n = nums.size();
  13.         if (n == 0) {
  14.             return ans;
  15.         }
  16.         sort(nums.begin(), nums.end());
  17.         b.resize(n, false);
  18.         DFS(nums, 0);
  19.         return ans;
  20.     }
  21. private:
  22.     vector<vector<int> > ans;
  23.     vector<int> p;
  24.     vector<bool> b;
  25.     int n;
  26.    
  27.     void DFS(vector<int> &nums, int idx) {
  28.         if (idx == n) {
  29.             ans.push_back(p);
  30.             return;
  31.         }
  32.         int i;
  33.         for (i = 0; i < n; ++i) {
  34.             if (b[i]) {
  35.                 continue;
  36.             }
  37.             p.push_back(nums[i]);
  38.             b[i] = true;
  39.             DFS(nums, idx + 1);
  40.             b[i] = false;
  41.             p.pop_back();
  42.         }
  43.     }
  44. };
复制代码
复杂度2:时间O(N * N!),空间O(N!)。

补充内容 (2015-7-21 19:10):
回复水逼一枚:不用API也可以啊,自己实现next_permutation即可。另外,讨论最好用回帖的形式吧,否则我没地方回复。

点评

请问这个题你的解法I,是借助C++的API是吗?有没有考虑过不借助API实现非递归的方法呢?  发表于 2015-7-21 05:10
回复

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-18 17:50:27 | 只看该作者
全局:
Permutations II
题意:给定一个可能包含重复元素的数组,求所有可能的排列。
解法:自己实现一个next_permutation。时间复杂度为O(N)。
代码:
  1. #include <algorithm>
  2. using namespace std;

  3. class Solution {
  4. public:
  5.     /**
  6.      * @param nums: A list of integers.
  7.      * @return: A list of unique permutations.
  8.      */
  9.     vector<vector<int> > permuteUnique(vector<int> &nums) {
  10.         ans.clear();
  11.         int n = nums.size();
  12.         if (n == 0) {
  13.             return ans;
  14.         }
  15.         sort(nums.begin(), nums.end());
  16.         do {
  17.             ans.push_back(nums);
  18.         } while (nextPermutation(nums));
  19.         return ans;
  20.     }
  21. private:
  22.     vector<vector<int> > ans;
  23.    
  24.     bool nextPermutation(vector<int> &a) {
  25.         int n = a.size();
  26.         int i, j;
  27.         for (i = n - 2; i >= 0; --i) {
  28.             if (a[i] < a[i + 1]) {
  29.                 break;
  30.             }
  31.         }
  32.         if (i < 0) {
  33.             return false;
  34.         }
  35.         j = n - 1;
  36.         while (a[j] <= a[i]) {
  37.             --j;
  38.         }
  39.         swap(a[i], a[j]);
  40.         reverse(a.begin() + i + 1, a.end());
  41.         
  42.         return true;
  43.     }
  44. };
复制代码
复杂度:时间O(N * N!),空间O(1)。
回复

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-18 21:26:37 | 只看该作者
全局:
Subsets
题意:给定一个集合,求它的幂集。
解法1:有N个元素,则有2^N个子集,从0~2^N - 1逐个遍历即可。
代码1:
  1. // The iterative solution
  2. #include <algorithm>
  3. using namespace std;

  4. class Solution {
  5. public:
  6.     /**
  7.      * @param S: A set of numbers.
  8.      * @return: A list of lists. All valid subsets.
  9.      */
  10.     vector<vector<int> > subsets(vector<int> &nums) {
  11.         int n = nums.size();
  12.         if (n == 0) {
  13.             return ans;
  14.         }
  15.         vector<int> s;
  16.         int i, j;
  17.         int n2 = 1 << n;
  18.         for (i = 0; i < n2; ++i) {
  19.             for (j = 0; j < n; ++j) {
  20.                 if (i & (1 << j)) {
  21.                     s.push_back(nums[j]);
  22.                 }
  23.             }
  24.             ans.push_back(s);
  25.             s.clear();
  26.         }
  27.         return ans;
  28.     }
  29. private:
  30.     vector<vector<int> > ans;
  31. };
复制代码
复杂度1:时间O(N * 2 ^ N),空间O(N)。

解法2:使用递归,写法也比较简单。每个元素都有选或者不选两种。
代码2:
  1. // The recursive solution
  2. #include <algorithm>
  3. using namespace std;

  4. class Solution {
  5. public:
  6.     /**
  7.      * @param S: A set of numbers.
  8.      * @return: A list of lists. All valid subsets.
  9.      */
  10.     vector<vector<int> > subsets(vector<int> &nums) {
  11.         n = nums.size();
  12.         if (n == 0) {
  13.             return ans;
  14.         }
  15.         DFS(nums, 0);
  16.         return ans;
  17.     }
  18. private:
  19.     vector<vector<int> > ans;
  20.     vector<int> s;
  21.     int n;
  22.    
  23.     void DFS(vector<int> &a, int idx) {
  24.         if (idx == n) {
  25.             ans.push_back(s);
  26.             return;
  27.         }
  28.         
  29.         DFS(a, idx + 1);
  30.         s.push_back(a[idx]);
  31.         DFS(a, idx + 1);
  32.         s.pop_back();
  33.     }
  34. };
复制代码
复杂度2:时间O(N * 2 ^ N),空间O(2 ^ N)。
回复

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-18 21:51:39 | 只看该作者
全局:
Subsets II
题意:给定一个multiset,求其所有子集。
解法:因为可以包含重复元素,所以此时子集的个数不一定是2 ^ N个了,所以改用递归。最好把诸如[2, 2, 2]这样的重复元素变成<2, 3>这样的键值对,因为可以在递归时提高效率。
代码:
  1. // The recursive solution
  2. #include <algorithm>
  3. using namespace std;

  4. class Solution {
  5. public:
  6.     /**
  7.      * @param S: A set of numbers.
  8.      * @return: A list of lists. All valid subsets.
  9.      */
  10.     vector<vector<int> > subsetsWithDup(const vector<int> &S) {
  11.         ans.clear();
  12.         n = S.size();
  13.         if (n == 0) {
  14.             return ans;
  15.         }
  16.         int i, j;
  17.         int cc;
  18.         
  19.         vector<int> ss;
  20.         for (i = 0; i < n; ++i) {
  21.             ss.push_back(S[i]);
  22.         }
  23.         sort(ss.begin(), ss.end());
  24.         a.clear();
  25.         c.clear();
  26.         i = 0;
  27.         while (i < n) {
  28.             j = i + 1;
  29.             while (j < n && ss[i] == ss[j]) {
  30.                 ++j;
  31.             }
  32.             cc = j - i;
  33.             a.push_back(ss[i]);
  34.             c.push_back(cc);
  35.             i = j;
  36.         }
  37.         n = a.size();
  38.         DFS(0);
  39.         return ans;
  40.     }
  41. private:
  42.     vector<vector<int> > ans;
  43.     vector<int> s;
  44.     vector<int> a;
  45.     vector<int> c;
  46.     int n;
  47.    
  48.     void DFS(int idx) {
  49.         if (idx == n) {
  50.             ans.push_back(s);
  51.             return;
  52.         }
  53.         int i, j;
  54.         for (i = 0; i <= c[idx]; ++i) {
  55.             for (j = 0; j < i; ++j) {
  56.                 s.push_back(a[idx]);
  57.             }
  58.             DFS(idx + 1);
  59.             for (j = 0; j < i; ++j) {
  60.                 s.pop_back();
  61.             }
  62.         }
  63.     }
  64. };
复制代码
复杂度:如果每个不重复元素A{i}出现次数为C{i},那么时间复杂度为PI(C{i})。(PI是连乘)
回复

使用道具 举报

🔗
stellari 2015-7-18 22:02:48 | 只看该作者
全局:
zhuli19901106 发表于 2015-7-18 15:50
A + B Problem
题意:求32位整数之和A + B
解法:直接相加就不提了。此处可以考虑用全加器的原理,纯位操 ...

这里没有使用循环。有什么特殊原因吗?
回复

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-18 22:05:22 | 只看该作者
全局:
Search a 2D Matrix
题意:给定一个二维数组,每行都是有序的,而且每行的末尾都不大于下一行的行首。在这个数组中查找一个值。
解法:其实就是要我们展开成一维数组,然后二分搜索。
代码:
  1. class Solution {
  2. public:
  3.     /**
  4.      * @param matrix, a list of lists of integers
  5.      * @param target, an integer
  6.      * [url=home.php?mod=space&uid=160137]@return[/url] a boolean, indicate whether matrix contains target
  7.      */
  8.     bool searchMatrix(vector<vector<int> > &matrix, int target) {
  9.         int n, m;
  10.         n = matrix.size();
  11.         if (n == 0) {
  12.             return false;
  13.         }
  14.         m = matrix[0].size();
  15.         if (m == 0) {
  16.             return false;
  17.         }
  18.         if (target < matrix[0][0] || target > matrix[n - 1][m - 1]) {
  19.             return false;
  20.         }
  21.         int ll, rr, mm;
  22.         
  23.         ll = 0;
  24.         rr = n * m - 1;
  25.         while (ll <= rr) {
  26.             mm = (ll + rr) / 2;
  27.             if (matrix[mm / m][mm % m] < target) {
  28.                ll = mm + 1;
  29.             } else if (matrix[mm / m][mm % m] > target) {
  30.                 rr = mm - 1;
  31.             } else {
  32.                 return true;
  33.             }
  34.         }
  35.         return false;
  36.     }
  37. };
复制代码
复杂度:时间O(log(N * M)),空间O(1)。
回复

使用道具 举报

🔗
stellari 2015-7-18 22:05:55 | 只看该作者
全局:
zhuli19901106 发表于 2015-7-18 16:26
Kth Largest Element
题意:求一个数组中,第K大的数。允许交换数组中的元素。
解法:根据快排改造得到快 ...

quickSelect可以简单地写成迭代形式的啊。那样空间复杂度就是O(1)了。
回复

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-18 22:06:58 | 只看该作者
全局:
stellari 发表于 2015-7-18 22:02
这里没有使用循环。有什么特殊原因吗?

因为题目要求不准用加法,用++i或者foreach之类的实质上都要用到加法,所以我特意按照verilog的风格写了32个函数。
回复

使用道具 举报

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

本版积分规则

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