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

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

 
🔗
sevenwonder 2015-7-23 23:35:35 | 只看该作者
全局:
zhuli19901106 发表于 2015-7-23 21:29
好吧,如果是程序计算文本相似度来过滤垃圾信息的话,那也没办法了。。
我也不能每题换种语言去写@_@

楼主加油,支持你!
回复

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-23 23:39:24 | 只看该作者
全局:
Wildcard Matching
题意:hard难度。实现通配符的功能。
解法:个人觉得这题和正则匹配是这里面最难的题之一。为了处理*,依然是要处理匹配失败时的回溯问题。不过这题的回溯方法比正则要简单,只用保存最后一个*的位置。
代码:
  1. #include <cstring>
  2. using namespace std;

  3. class Solution {
  4. public:
  5.     /**
  6.      * @param s: A string
  7.      * @param p: A string includes "?" and "*"
  8.      * @return: A boolean
  9.      */
  10.     bool isMatch(const char *s, const char *p) {
  11.         if (s == NULL || p == NULL) {
  12.             return false;
  13.         }
  14.         int ls = strlen(s);
  15.         int lp = strlen(p);
  16.         if (lp == 0) {
  17.             return ls == 0;
  18.         }
  19.         
  20.         int i, j;
  21.         int star_s, star_p;
  22.         
  23.         i = j = 0;
  24.         star_s = star_p = -1;
  25.         while (i < ls) {
  26.             if (p[j] == '?' || s[i] == p[j]) {
  27.                 ++i;
  28.                 ++j;
  29.             } else if (p[j] == '*') {
  30.                 star_p = j++;
  31.                 star_s = i;
  32.             } else if (star_p != -1) {
  33.                 i = ++star_s;
  34.                 j = star_p + 1;
  35.             } else {
  36.                 return false;
  37.             }
  38.         }
  39.         while (j < lp && p[j] == '*') {
  40.             ++j;
  41.         }
  42.         return j == lp;
  43.     }
  44. };
复制代码
复杂度:时间O(N ^ 2),空间O(1)。
回复

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-23 23:46:21 | 只看该作者
全局:
sun403 发表于 2015-7-23 22:46
Lintcode上 space replacement  程序中return的是int数据, 题目要求是输出最后的string,楼主怎么写的这部 ...

这题可以从头到尾扫一遍,看有多少个空格。
然后从尾到头扫一遍,碰见空格就写“%20”,碰见其他字符就直接写。
因为第一遍已经确定了空格的个数,所以第二遍每个字符该放哪儿都是可以确定的。这题在后面,我还得有几天才能写到。
回复

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-23 23:58:40 | 只看该作者
全局:
Segment Tree Build
题意:线段树的构造。对于搞竞赛的人,线段树肯定是贴身宝贝。对于我们这些没搞过的,就很陌生了。所以要学一下。
解法:依题意来。纯线段树当然是很耗空间的。此处顺便提一下:“mm = (ll + rr) / 2;”这种写法是错误的,学数值分析时第一堂课老师就讲这个。
代码:
  1. /**
  2. * Definition of SegmentTreeNode:
  3. * class SegmentTreeNode {
  4. * public:
  5. *     int start, end;
  6. *     SegmentTreeNode *left, *right;
  7. *     SegmentTreeNode(int start, int end) {
  8. *         this->start = start, this->end = end;
  9. *         this->left = this->right = NULL;
  10. *     }
  11. * }
  12. */
  13. typedef SegmentTreeNode STN;
  14. class Solution {
  15. public:
  16.     /**
  17.      *@param start, end: Denote an segment / interval
  18.      *@return: The root of Segment Tree
  19.      */
  20.     STN *build(int start, int end) {
  21.         if (start > end) {
  22.             return NULL;
  23.         }
  24.         STN *root = new STN(start, end);
  25.         if (start == end) {
  26.             return root;
  27.         }
  28.         int mid = start + (end - start) / 2;
  29.         root->left = build(start, mid);
  30.         root->right = build(mid + 1, end);
  31.         return root;
  32.     }
  33. };
复制代码
复杂度:时间O(N * log(N)),空间一样。
回复

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-24 03:03:27 | 只看该作者
全局:
本帖最后由 zhuli19901106 于 2015-7-24 03:24 编辑

说到线段树,想起了POJ上一道线段树入门题我还没做,于是跑去写。
http://poj.org/problem?id=2528
没想到leetcode做久了,已经忘了POJ坑爹的风格:常数优化。
从一开始以为很快就能AC,到后来越写bug越多,各种调优。中途POJ服务器还挂了好几次。到AC的时候,已经半夜三点了(T_T)
  1. // 2528        Accepted        10872K        94MS        G++        3383B        2015-07-24 02:49:48
  2. #include <algorithm>
  3. #include <cstdio>
  4. #include <cstring>
  5. using namespace std;

  6. const int N = 100005;
  7. int s[N];
  8. int e[N];

  9. int d1[2 * N];
  10. int dc1;

  11. int d[3 * N];
  12. int dc;

  13. int n;
  14. int b[N];
  15. int ans;

  16. typedef struct SegmentTreeNode {
  17.     int start, end;
  18.     int tag;
  19.     SegmentTreeNode *left, *right;
  20.    
  21.     SegmentTreeNode(int _start = 0, int _end = 0) {
  22.         start = _start;
  23.         end = _end;
  24.         tag = -1;
  25.         left = right = NULL;
  26.     }
  27. } STN;
  28. const int MAX_NODE = 500000;
  29. STN nodes[MAX_NODE];
  30. int nc;

  31. int mymin(int x, int y)
  32. {
  33.     return x < y ? x : y;
  34. }

  35. int mymax(int x, int y)
  36. {
  37.     return x > y ? x : y;
  38. }

  39. STN *buildTree(int start, int end)
  40. {
  41.     if (start > end) {
  42.         return NULL;
  43.     }
  44.     STN *root = &(nodes[nc++]);
  45.     root->start = start;
  46.     root->end = end;
  47.     if (start == end) {
  48.         return root;
  49.     }
  50.     int mid = start + (end - start >> 1);
  51.     if (mid < end) {
  52.         root->left = buildTree(start, mid);
  53.     }
  54.     if (mid + 1 > start) {
  55.         root->right = buildTree(mid + 1, end);
  56.     }
  57.     return root;
  58. }

  59. void addPoster(STN *root, int start, int end, int tag)
  60. {
  61.     if (start > end) {
  62.         return;
  63.     }
  64.     if (start == root->start && end == root->end) {
  65.         root->tag = tag;
  66.         return;
  67.     }
  68.     int mid = root->start + (root->end - root->start >> 1);
  69.     int oldtag = root->tag;
  70.     root->tag = -1;
  71.     if (oldtag >= 0) {
  72.         addPoster(root, root->start, start - 1, oldtag);
  73.         addPoster(root, end + 1, root->end, oldtag);
  74.     }
  75.    
  76.     addPoster(root->left, start, mymin(mid, end), tag);
  77.     addPoster(root->right, mymax(mid + 1, start), end, tag);
  78. }

  79. void countPoster(STN *root)
  80. {
  81.     if (root == NULL) {
  82.         return;
  83.     }
  84.     if (root->tag >= 0) {
  85.         if (!b[root->tag]) {
  86.             b[root->tag] = 1;
  87.             ++ans;
  88.         }
  89.         return;
  90.     }
  91.     countPoster(root->left);
  92.     countPoster(root->right);
  93. }

  94. void discretization()
  95. {
  96.     dc = 0;
  97.     d[dc++] = d1[0];
  98.     int i;
  99.     for (i = 1; i < dc1; ++i) {
  100.         if (d1[i] - d1[i - 1] > 1) {
  101.             d[dc++] = d1[i - 1] + (d1[i] - d1[i - 1] >> 1);
  102.         }
  103.         d[dc++] = d1[i];
  104.     }
  105. }

  106. void clearTree(STN *root)
  107. {
  108.     if (root == NULL) {
  109.         return;
  110.     }
  111.     clearTree(root->left);
  112.     clearTree(root->right);

  113.     root->left = NULL;
  114.     root->right = NULL;
  115.     root->tag = -1;
  116.     --nc;
  117. }

  118. int removeDuplicate(int a[], int n)
  119. {
  120.     int i, j;
  121.     int n1 = 0;

  122.     i = 0;
  123.     while (i < n) {
  124.         j = i + 1;
  125.         while (j < n && a[i] == a[j]) {
  126.             ++j;
  127.         }
  128.         a[n1++] = a[i];
  129.         i = j;
  130.     }
  131.     return n1;
  132. }

  133. int bs(int x)
  134. {
  135.     int ll = 0;
  136.     int rr = dc - 1;
  137.     int mm;
  138.     while (ll <= rr) {
  139.         mm = ll + (rr - ll >> 1);
  140.         if (x < d[mm]) {
  141.             rr = mm - 1;
  142.         } else if (x > d[mm]) {
  143.             ll = mm + 1;
  144.         } else {
  145.             return mm;
  146.         }
  147.     }
  148.     return -1;
  149. }

  150. void solve()
  151. {
  152.     scanf("%d", &n);
  153.    
  154.     int i;
  155.     dc1 = 0;
  156.     for (i = 0; i < n; ++i) {
  157.         scanf("%d%d", &s[i], &e[i]);
  158.         d1[dc1++] = s[i];
  159.         d1[dc1++] = e[i];
  160.     }
  161.     sort(d1, d1 + dc1);
  162.     dc1 = removeDuplicate(d1, dc1);
  163.    
  164.     discretization();
  165.    
  166.     STN *root = buildTree(0, dc - 1);
  167.     for (i = 0; i < n; ++i) {
  168.         addPoster(root, bs(s[i]), bs(e[i]), i);
  169.     }
  170.    
  171.     ans = 0;
  172.     memset(b, 0, sizeof(b));
  173.     countPoster(root);
  174.     printf("%d\n", ans);
  175.    
  176.     clearTree(root);
  177. }

  178. int main()
  179. {
  180.     int t, ti;
  181.    
  182.     scanf("%d", &t);
  183.     for (ti = 0; ti < t; ++ti) {
  184.         solve();
  185.     }
  186.    
  187.     return 0;
  188. }
复制代码
思维有多乱,代码就有多烂。我自己都晕了。

也借这题说说C/C++常系数优化的事吧:
1. set和map很好用,但是手写二分比它们要快。
2. sort函数效率很高,自己手写快排没它快。
3. vector的效率和数组差了好几倍。
4. memset比fill要快
5. new东西很慢,用全局数组比逐个动态分配会快很多。
6. 递归效率不一定低,写法是关键。
7. cin比scanf慢10倍。但如果用了ios::sync_with_stdio(false);则不再需要和C的缓冲区保持同步,于是速度几乎一样了。
8. 位运算可以代替2相关的乘除法,速度差别很大。
9. emplace_back比push_back快点,因为少了一次复制。
把上面的优化技巧都用到了,这题就能在100ms内AC,都不用的话就严重超时。然而,这些都跟复杂度没半毛钱关系。复杂度始终是一样的。
这就是《编程珠玑》里提到的“程序调优”。

回复

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-24 03:34:59 | 只看该作者
全局:
Segment Tree Query
题意:RMQ问题。只要求实现query函数。
解法:分情况讨论的话,代码会很复杂。应该尽量搞简单点。
代码:
  1. #include <algorithm>
  2. #include <climits>
  3. using namespace std;
  4. /**
  5. * Definition of SegmentTreeNode:
  6. * class SegmentTreeNode {
  7. * public:
  8. *     int start, end, max;
  9. *     SegmentTreeNode *left, *right;
  10. *     SegmentTreeNode(int start, int end, int max) {
  11. *         this->start = start;
  12. *         this->end = end;
  13. *         this->max = max;
  14. *         this->left = this->right = NULL;
  15. *     }
  16. * }
  17. */
  18. typedef SegmentTreeNode STN;
  19. class Solution {
  20. public:
  21.     /**
  22.      *@param root, start, end: The root of segment tree and
  23.      *                         an segment / interval
  24.      *@return: The maximum number in the interval [start, end]
  25.      */
  26.     int query(STN *root, int start, int end) {
  27.         if (start > end) {
  28.             return INT_MIN;
  29.         }
  30.         if (start == root->start && end == root->end) {
  31.             return root->max;
  32.         }
  33.         int mid = root->start + (root->end - root->start >> 1);
  34.         int ans = INT_MIN;
  35.         ans = max(ans, query(root->left, start, min(end, mid)));
  36.         ans = max(ans, query(root->right, max(start, mid + 1), end));
  37.         return ans;
  38.     }
  39. };
复制代码
复杂度:时间O(log(N)),空间O(log(N))。整棵树的空间不算在query的复杂度里。
回复

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-24 03:41:49 | 只看该作者
全局:
Segment Tree Modify
题意:RMQ问题。这回要实现修改单个元素的功能。
解法:逐步向下搜索,然后反过来向上更新最大值。
代码:
  1. /**
  2. * Definition of SegmentTreeNode:
  3. * class SegmentTreeNode {
  4. * public:
  5. *     int start, end, max;
  6. *     SegmentTreeNode *left, *right;
  7. *     SegmentTreeNode(int start, int end, int max) {
  8. *         this->start = start;
  9. *         this->end = end;
  10. *         this->max = max;
  11. *         this->left = this->right = NULL;
  12. *     }
  13. * }
  14. */
  15. class Solution {
  16. public:
  17.     /**
  18.      *@param root, index, value: The root of segment tree and
  19.      *@ change the node's value with [index, index] to the new given value
  20.      *@return: void
  21.      */
  22.     void modify(SegmentTreeNode *root, int index, int value) {
  23.         if (root->start == root->end) {
  24.             root->max = value;
  25.             return;
  26.         }
  27.         int mid = root->start + (root->end - root->start) / 2;
  28.         if (index <= mid) {
  29.             modify(root->left, index, value);
  30.         } else {
  31.             modify(root->right, index, value);
  32.         }
  33.         root->max = max(root->left->max, root->right->max);
  34.     }
  35. };
复制代码
复杂度:时间O(log(N)),空间O(log(N))。
回复

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-24 04:02:32 | 只看该作者
全局:
本帖最后由 zhuli19901106 于 2015-7-24 04:03 编辑

Singleton
题意:实现单体模式。
解法:C++的写法中有个语法问题,看最后一行代码。另外,如果要对多线程适用的话,就得加锁。
代码:
  1. class Solution {
  2. public:
  3.     static Solution *getInstance() {
  4.         if (instance == NULL) {
  5.             instance = new Solution();
  6.         }
  7.                 return instance;
  8.     }
  9. private:
  10.     Solution();
  11.     static Solution *instance;
  12. };
  13. Solution *Solution::instance = NULL;
复制代码
复杂度:非算法题。
回复

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-24 04:30:57 | 只看该作者
全局:
Interval Minimum Number
题意:RMQ问题。
解法:使用ST算法。这题对搞竞赛的人有好几种解法,我只选最好写的ST算法。其他解法还包括线段树、笛卡尔树,肯定没这个好写就是了。
代码:
  1. // Solution using sparse table
  2. #include <algorithm>
  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. class Solution {
  14. public:
  15.     /**
  16.      *@param A, queries: Given an integer array and an query list
  17.      *@return: The result list
  18.      */
  19.     vector<int> intervalMinNumber(vector<int> &A, vector<Interval> &queries) {
  20.         // Sparse table
  21.         vector<vector<int> > st;
  22.         int base = 1;
  23.         int n = A.size();
  24.         int m = 1;
  25.         while (base << 1 <= n) {
  26.             base <<= 1;
  27.             ++m;
  28.         }
  29.         base = 1;
  30.         st.resize(m);
  31.         
  32.         int i;
  33.         for (i = 0; i < m; ++i) {
  34.             st[i].resize(n - base + 1);
  35.             base <<= 1;
  36.         }
  37.         
  38.         for (i = 0; i < n; ++i) {
  39.             st[0][i] = A[i];
  40.         }
  41.         
  42.         int j;
  43.         base = 1;
  44.         for (i = 1; i < m; ++i) {
  45.             base <<= 1;
  46.             for (j = 0; j + base <= n; ++j) {
  47.                 st[i][j] = min(st[i - 1][j], st[i - 1][j + (base >> 1)]);
  48.             }
  49.         }
  50.         
  51.         m = queries.size();
  52.         int x, y;
  53.         vector<int> ans;
  54.         for (i = 0; i < m; ++i) {
  55.             x = queries[i].start;
  56.             y = queries[i].end;
  57.             base = 1;
  58.             j = 0;
  59.             while (base << 1 <= y - x + 1) {
  60.                 base <<= 1;
  61.                 ++j;
  62.             }
  63.             ans.push_back(min(st[j][x], st[j][y + 1 - base]));
  64.         }
  65.         return ans;
  66.     }
  67. };
复制代码
复杂度:预处理时间O(N * log(N)),每次query时间O(log(N)),空间O(N * log(N))。
回复

使用道具 举报

🔗
水逼一枚 2015-7-24 06:01:01 | 只看该作者
全局:
本帖最后由 水逼一枚 于 2015-7-24 06:05 编辑
zhuli19901106 发表于 2015-7-22 03:11
Longest Consecutive Sequence
题意:给定一个无序数组,求其中能够组成的最长连续序列。比如[100, 4, 200 ...

我想问一下,像这个题还有类似的题目出现过的吗?就是利用HashMap左右延展来解题这类似的题目?这题想了好一会儿都没想到要往Hash结构上靠。。智商太捉急了。。感觉各种hard题目都是出在array上,有啥心得吗?还有就是这个题能用DP吗?如果不能用DP是为啥不能呢?谢谢!
回复

使用道具 举报

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

本版积分规则

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