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

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

 
🔗
 楼主| zhuli19901106 2015-7-25 01:45:00 | 只看该作者
全局:
Count of Smaller Number before itself
题意:hard难度。给定一个整数数组,元素都介于0-10000之间。对于每个元素A{i},求它前面有多少个比它小的。
解法:这题又用到了树状数组,注意0-10000这个条件的作用。如果我们直接开个长度为10001的数组B,对于每个A{i},都把B的对应位置B{A{i}}加上1,那么A{i}前面比它小的元素的个数,就等于B{0} + B{1} + ... + B{A{i} - 1}。于是,能够快速求和的树状数组就派上用场了。
这题如果数据较大的话,比如两亿,那么就得通过离散化的思路映射成小数据。
代码:
  1. class Solution {
  2. public:
  3.    /**
  4.      * @param A: An integer array
  5.      * @return: Count the number of element before this element 'ai' is
  6.      *          smaller than it and return count number array
  7.      */
  8.     vector<int> countOfSmallerNumberII(vector<int> &A) {
  9.         vector<int> s(N + 1, 0);
  10.         vector<int> ans;
  11.         int n = A.size();
  12.         int i;
  13.         for (i = 0; i < n; ++i) {
  14.             // Offset by 1
  15.             ans.push_back(sum(s, A[i]));
  16.             add(s, A[i] + 1, 1);
  17.         }
  18.         return ans;
  19.     }
  20. private:
  21.     static const int N = 10001;
  22.    
  23.     int lowbit(int x) {
  24.         return x & -x;
  25.     }
  26.    
  27.     int sum(vector<int> &a, int i) {
  28.         int sum = 0;
  29.         while (i > 0) {
  30.             sum += a[i];
  31.             i -= lowbit(i);
  32.         }
  33.         return sum;
  34.     }
  35.    
  36.     void add(vector<int> &a, int i, int val) {
  37.         if (i == 0) {
  38.             return;
  39.         }
  40.         while (i <= N) {
  41.             a[i] += val;
  42.             i += lowbit(i);
  43.         }
  44.     }
  45. };
复制代码
复杂度:时间O(N * log(M)),其中M表示数组元素的范围,此处是10000。空间是O(M)。
回复

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-25 01:51:23 | 只看该作者
全局:
Longest Substring with At Most K Distinct Characters
题意:给定一个字符串,求至多包含K种不同字符的最长字串。
解法:依然是用首尾两个指针,边移动边统计字符个数,字符种类的方法。扫描过程中随时更新结果。
代码:
  1. #include <cstring>
  2. using namespace std;

  3. class Solution {
  4. public:
  5.     /**
  6.      * @param s : A string
  7.      * @return : The length of the longest substring
  8.      *           that contains at most k distinct characters.
  9.      */
  10.     int lengthOfLongestSubstringKDistinct(string s, int k) {
  11.         int c[256];
  12.         int n = s.length();
  13.         
  14.         if (n == 0 || k == 0) {
  15.             return 0;
  16.         }
  17.         
  18.         int ans = 0;
  19.         memset(c, 0, sizeof(c));
  20.         int cc = 0;
  21.         int i, j;
  22.         i = j = 0;
  23.         while (j < n) {
  24.             if (c[s[j]] == 0) {
  25.                 ++cc;
  26.             }
  27.             ++c[s[j]];
  28.             if (cc <= k) {
  29.                 ans = max(ans, j - i + 1);
  30.                 ++j;
  31.                 continue;
  32.             }
  33.             while (cc > k) {
  34.                 --c[s[i]];
  35.                 if (c[s[i]] == 0) {
  36.                     --cc;
  37.                 }
  38.                 ++i;
  39.             }
  40.             ++j;
  41.         }
  42.         return ans;
  43.     }
  44. };
复制代码
复杂度:时间O(N),空间O(1)。
回复

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-25 03:07:25 | 只看该作者
全局:
The Smallest Difference
题意:给定两个数组A和B,任选i和j,求A{i}和B{j}的最小差值。
解法1:排好序,一个遍历,一个二分。
代码1:
  1. // O(n * log(n)) solution with O(1) space
  2. #include <algorithm>
  3. #include <climits>
  4. using namespace std;

  5. class Solution {
  6. public:
  7.     /**
  8.      * @param A, B: Two integer arrays.
  9.      * @return: Their smallest difference.
  10.      */
  11.     int smallestDifference(vector<int> &A, vector<int> &B) {
  12.         if (A.size() > B.size()) {
  13.             return smallestDifference(B, A);
  14.         }
  15.         
  16.         sort(A.begin(), A.end());
  17.         sort(B.begin(), B.end());
  18.         
  19.         int i, j;
  20.         int ans = INT_MAX;
  21.         int na = A.size();
  22.         int nb = B.size();
  23.         
  24.         for (i = 0; i < na; ++i) {
  25.             j = lower_bound(B.begin(), B.end(), A[i]) - B.begin();
  26.             if (j < nb) {
  27.                 ans = min(ans, B[j] - A[i]);
  28.             }
  29.             if (j > 0) {
  30.                 ans = min(ans, A[i] - B[j - 1]);
  31.             }
  32.         }
  33.         return ans;
  34.     }
  35. };
复制代码
复杂度1:时间O(N * log(N)),空间O(1)。

解法2:排好序,归并成一个数组,不过要标记每个元素是来自A还是来自B。然后求最小差值。这做法虽然在理论复杂度上没优势,不过后面的归并过程是线性时间,所以还是会快些的。
代码2:
  1. // O(n * log(n)) solution with O(n) space
  2. #include <algorithm>
  3. using namespace std;

  4. int abs(int x)
  5. {
  6.     return x >= 0 ? x : -x;
  7. }

  8. class Solution {
  9. public:
  10.     /**
  11.      * @param A, B: Two integer arrays.
  12.      * @return: Their smallest difference.
  13.      */
  14.     int smallestDifference(vector<int> &A, vector<int> &B) {
  15.         sort(A.begin(), A.end());
  16.         sort(B.begin(), B.end());
  17.         
  18.         vector<int> tag;
  19.         vector<int> C;
  20.         
  21.         int na = A.size();
  22.         int nb = B.size();
  23.         int i, j;
  24.         i = j = 0;
  25.         while (i < na && j < nb) {
  26.             if (A[i] < B[j]) {
  27.                 C.push_back(A[i++]);
  28.                 tag.push_back(0);
  29.             } else {
  30.                 C.push_back(B[j++]);
  31.                 tag.push_back(1);
  32.             }
  33.         }
  34.         if (i < na) {
  35.             C.push_back(A[i++]);
  36.             tag.push_back(0);
  37.         } else {
  38.             C.push_back(B[j++]);
  39.             tag.push_back(1);
  40.         }
  41.         
  42.         int n = C.size();
  43.         int ans = INT_MAX;
  44.         for (i = 0; i < n - 1; ++i) {
  45.             if (tag[i] ^ tag[i + 1]) {
  46.                 ans = min(ans, abs(C[i] - C[i + 1]));
  47.             }
  48.         }
  49.         
  50.         return ans;
  51.     }
  52. };
复制代码
复杂度2:时间O(N * log(N)),空间O(N)。
回复

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-25 03:10:54 | 只看该作者
全局:
Number of Airplanes in the Sky
题意:给定很多飞机的起降时间,请求出同一时刻天上最多有几架飞机。如果存在起降重合的,按照先降后起处理。
解法:这题起初没思路,往线段树那想了,结果没想出来。后来看了别人的解法,才发现可以和括号匹配问题联系起来想。细节参见下列代码。
代码:
  1. #include <algorithm>
  2. #include <utility>
  3. using namespace std;
  4. /**
  5. * Definition of Interval:
  6. * classs Interval {
  7. *     int start, end;
  8. *     Interval(int start, int end) {
  9. *         this->start = start;
  10. *         this->end = end;
  11. *     }
  12. */
  13. bool comp(const pair<int, int> &p1, const pair<int, int> &p2)
  14. {
  15.     if (p1.first != p2.first) {
  16.         return p1.first < p2.first;
  17.     } else {
  18.         return p1.second > p2.second;
  19.     }
  20. }

  21. class Solution {
  22. public:
  23.     /**
  24.      * @param intervals: An interval array
  25.      * @return: Count of airplanes are in the sky.
  26.      */
  27.     int countOfAirplanes(vector<Interval> &airplanes) {
  28.         vector<pair<int, int> > v;
  29.         pair<int, int> p;
  30.         int n = airplanes.size();
  31.         int i;
  32.         for (i = 0; i < n; ++i) {
  33.             p.first = airplanes[i].start;
  34.             p.second = 0;
  35.             v.push_back(p);
  36.             p.first = airplanes[i].end;
  37.             p.second = 1;
  38.             v.push_back(p);
  39.         }
  40.         sort(v.begin(), v.end(), comp);
  41.         int ans = 0;
  42.         int cnt = 0;
  43.         n = v.size();
  44.         for (i = 0; i < n; ++i) {
  45.             if (v[i].second == 0) {
  46.                 ++cnt;
  47.                 ans = max(ans, cnt);
  48.             } else {
  49.                 --cnt;
  50.             }
  51.         }
  52.         return ans;
  53.     }
  54. };
复制代码
复杂度:时间O(N * log(N)),空间O(N)。
回复

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-25 03:14:14 | 只看该作者
全局:
Longest Substring Without Repeating Characters
题意:给定一个字符串,求出不含重复字符的最长字串。
解法:依然是两个指针向前走,随时统计字符个数,随时更新结果。
代码:
  1. #include <cstring>
  2. using namespace std;

  3. class Solution {
  4. public:
  5.     /**
  6.      * @param s: a string
  7.      * @return: an integer
  8.      */
  9.     int lengthOfLongestSubstring(string s) {
  10.         int c[256];
  11.         int n = s.length();
  12.         int i, j;
  13.         int ans = 0;
  14.         
  15.         memset(c, 0, sizeof(c));
  16.         i = j = 0;
  17.         while (j < n) {
  18.             if (c[s[j]]) {
  19.                 while (c[s[j]]) {
  20.                     --c[s[i++]];
  21.                 }
  22.                 c[s[j]] = 1;
  23.             } else {
  24.                 c[s[j]] = 1;
  25.                 ans = max(ans, j - i + 1);
  26.             }
  27.             ++j;
  28.         }
  29.         return ans;
  30.     }
  31. };
复制代码
复杂度:时间O(N),空间O(1)。
回复

使用道具 举报

🔗
水逼一枚 2015-7-25 08:04:09 | 只看该作者
全局:
zhuli19901106 发表于 2015-7-18 21:51
Subsets II
题意:给定一个multiset,求其所有子集。
解法:因为可以包含重复元素,所以此时子集的个数不 ...

26楼的SubsetsII这个题目,如果不用sort有什么方法可以解决吗?我在一个群里看到有人再问,也来随便问下。目前想的是可以用hash。楼主有啥想法没呢?
回复

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-25 14:47:51 | 只看该作者
全局:
本帖最后由 zhuli19901106 于 2015-7-25 15:00 编辑
水逼一枚 发表于 2015-7-25 08:04
26楼的SubsetsII这个题目,如果不用sort有什么方法可以解决吗?我在一个群里看到有人再问,也来随便问下 ...

这题的复杂度是指数的,所以用排序对性能的影响可以忽略不计。另外,题目要求不重复、而且每个子集内部必须有序,所以不排序貌似没什好处啊。何乐而不为?
另外,哈希表是无序的,不能保证送进去的元素能够以有序的形式拿出来。如何保证结果中的每个子集有序呢?
私以为题目中经常提示你“能否在不用XXX的情况下完成题目”,是为了鼓励你多想不同思路。但不要刻意为了不用XXX而绞尽脑汁。比如不让你用map,你可以改用数组+排序+二分查找。这种思路不同,但是殊途同归的做法是值得鼓励的。
再来个反例,能否在不用sort的情况下给数组排序?可以,自己手写快排、堆排或者归并。这种“不用”其实没什么意义。
最坏情况,如果你不用一样东西,就没法以同样的效率解出题来,那还是用吧。
回复

使用道具 举报

🔗
caffery24 2015-7-25 15:30:42 | 只看该作者
全局:
zhuli19901106 发表于 2015-7-24 22:44
不是,是研究生刚要开学~

楼主是学习的榜样啊,我也是要上ms,准备转cs,刷到90多题,就感觉好多没思路了。。。
回复

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-25 15:42:18 | 只看该作者
全局:
Container With Most Water
题意:给定从位置0~N-1的N个位置,告诉你每个位置的柱子高度。如果允许你选取两个位置作为两堵墙,那么这两堵墙加上地板能够存多少水?
解法:这题的解法很简单,思路却很巧妙,请先看代码然后想想为什么。我第一次碰见时想了很久都没想到这思路,后来,回过头来想其实这种解法可以按照动态规划的思路简化得来。
代码:
  1. class Solution {
  2. public:
  3.     /**
  4.      * @param heights: a vector of integers
  5.      * @return: an integer
  6.      */
  7.     int maxArea(vector<int> &heights) {
  8.         int i, j;
  9.         int ans = 0;
  10.         int n = heights.size();
  11.         
  12.         i = 0;
  13.         j = n - 1;
  14.         while (i < j) {
  15.             ans = max(ans, (j - i) * min(heights[j], heights[i]));
  16.             if (heights[i] < heights[j]) {
  17.                 ++i;
  18.             } else {
  19.                 --j;
  20.             }
  21.         }
  22.         return ans;
  23.     }
  24. };
复制代码
复杂度:时间O(N),空间O(1)。
回复

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-25 15:57:40 | 只看该作者
全局:
Print Numbers by Recursion
题意:一道无聊的题,为了考而考。
解法:”茴“字有四种写法,你知道吗?
代码:
  1. class Solution {
  2. public:
  3.     /**
  4.      * @param n: An integer.
  5.      * return : An array storing 1 to the largest number with n digits.
  6.      */
  7.     vector<int> numbersByRecursion(int n) {
  8.         ans.clear();
  9.         DFS(0, 0, n);
  10.         return ans;
  11.     }
  12. private:
  13.     vector<int> ans;
  14.    
  15.     void DFS(int num, int idx, int n) {
  16.         if (idx == n) {
  17.             if (num > 0) {
  18.                 ans.push_back(num);
  19.             }
  20.             return;
  21.         }
  22.         
  23.         int i;
  24.         for (i = 0; i < 10; ++i) {
  25.             DFS(num * 10 + i, idx + 1, n);
  26.         }
  27.     }
  28. };
复制代码
复杂度:懒得算。
回复

使用道具 举报

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

本版积分规则

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