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

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

 
🔗
 楼主| zhuli19901106 2015-7-22 04:37:00 | 只看该作者
全局:
Topological Sorting
题意:求拓扑排序。
解法1:逐个找出入度为0的节点。两层循环,效率不高。
代码1:
  1. // O(n ^ 2) solution
  2. #include <unordered_map>
  3. using namespace std;
  4. /**
  5. * Definition for Directed graph.
  6. * struct DirectedGraphNode {
  7. *     int label;
  8. *     vector<DirectedGraphNode *> neighbors;
  9. *     DirectedGraphNode(int x) : label(x) {};
  10. * };
  11. */
  12. typedef DirectedGraphNode DGN;
  13. class Solution {
  14. public:
  15.     /**
  16.      * @param graph: A list of Directed graph node
  17.      * @return: Any topological order for the given graph.
  18.      */
  19.     vector<DGN *> topSort(vector<DGN *> graph) {
  20.         unordered_map<DGN *, int> ind;
  21.         vector<DGN *> ans;
  22.         int n, m;
  23.         int i, j;
  24.         
  25.         n = graph.size();
  26.         for (i = 0; i < n; ++i) {
  27.             m = graph[i]->neighbors.size();
  28.             for (j = 0; j < m; ++j) {
  29.                 ++ind[graph[i]->neighbors[j]];
  30.             }
  31.         }
  32.         int cc;
  33.         vector<bool> v(n, false);
  34.         while (true) {
  35.             cc = 0;
  36.             for (i = 0; i < n; ++i) {
  37.                 if (v[i] || ind[graph[i]] != 0) {
  38.                     continue;
  39.                 }
  40.                 ++cc;
  41.                 v[i] = true;
  42.                 ans.push_back(graph[i]);
  43.                 m = graph[i]->neighbors.size();
  44.                 for (j = 0; j < m; ++j) {
  45.                     --ind[graph[i]->neighbors[j]];
  46.                 }
  47.             }
  48.             if (cc == 0) {
  49.                 break;
  50.             }
  51.         }
  52.         return ans;
  53.     }
  54. };
复制代码
复杂度1:时间O(N ^ 2),空间O(N)。

解法2:改成BFS。
代码2:
  1. // Solution using BFS
  2. #include <queue>
  3. #include <unordered_set>
  4. #include <unordered_map>
  5. using namespace std;
  6. /**
  7. * Definition for Directed graph.
  8. * struct DirectedGraphNode {
  9. *     int label;
  10. *     vector<DirectedGraphNode *> neighbors;
  11. *     DirectedGraphNode(int x) : label(x) {};
  12. * };
  13. */
  14. typedef DirectedGraphNode DGN;
  15. class Solution {
  16. public:
  17.     /**
  18.      * @param graph: A list of Directed graph node
  19.      * @return: Any topological order for the given graph.
  20.      */
  21.     vector<DGN *> topSort(vector<DGN *> graph) {
  22.         unordered_map<DGN *, int> ind;
  23.         vector<DGN *> ans;
  24.         int n, m;
  25.         int i, j;
  26.         
  27.         n = graph.size();
  28.         for (i = 0; i < n; ++i) {
  29.             m = graph[i]->neighbors.size();
  30.             for (j = 0; j < m; ++j) {
  31.                 ++ind[graph[i]->neighbors[j]];
  32.             }
  33.         }
  34.         int cc;
  35.         queue<DGN *> q;
  36.         unordered_set<DGN *> us;
  37.         
  38.         for (i = 0; i < n; ++i) {
  39.             if (ind[graph[i]] == 0) {
  40.                 q.push(graph[i]);
  41.             }
  42.         }
  43.         
  44.         DGN *p;
  45.         while (!q.empty()) {
  46.             p = q.front();
  47.             q.pop();
  48.             if (us.find(p) != us.end()) {
  49.                 // Already visited
  50.                 continue;
  51.             }
  52.             if (ind[p] > 0) {
  53.                 // In-degree is not zero
  54.                 q.push(p);
  55.                 continue;
  56.             }
  57.             
  58.             ans.push_back(p);
  59.             us.insert(p);
  60.             m = p->neighbors.size();
  61.             for (i = 0; i < m; ++i) {
  62.                 --ind[p->neighbors[i]];
  63.                 q.push(p->neighbors[i]);
  64.             }
  65.         }
  66.         return ans;
  67.     }
  68. };
复制代码
复杂度2:时间O(N + E),空间O(N + E)
回复

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-22 04:37:42 | 只看该作者
全局:
又被吞掉一题:Topological Sorting。
回复

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-22 04:39:49 | 只看该作者
全局:
Hash Function
题意:照题目要求,实现一个哈希函数。
解法:照题目要求。
代码:
  1. typedef long long int LL;

  2. class Solution {
  3. public:
  4.     /**
  5.      * @param key: A String you should hash
  6.      * @param HASH_SIZE: An integer
  7.      * @return an integer
  8.      */
  9.     int hashCode(string key,int HASH_SIZE) {
  10.         int n = key.size();
  11.         LL ans = 0;
  12.         int i;
  13.         for (i = 0; i < n; ++i) {
  14.             ans = (ans * 33 + key[i]) % HASH_SIZE;
  15.         }
  16.         return ans;
  17.     }
  18. };
复制代码
复杂度:时间O(N),空间O(1)。
回复

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-22 04:43:56 | 只看该作者
全局:
Rehashing
题意:当哈希表的load factor超过阈值之后,性能会显著下降。于是此时需要扩大容量。请完成rehash操作。
解法:算好位置,插入。
代码:
  1. // This problem is a bit unreasonable.
  2. // Why must the nodes be appended to the end of the list?
  3. /**
  4. * Definition of ListNode
  5. * class ListNode {
  6. * public:
  7. *     int val;
  8. *     ListNode *next;
  9. *     ListNode(int val) {
  10. *         this->val = val;
  11. *         this->next = NULL;
  12. *     }
  13. * }
  14. */
  15. class Solution {
  16. public:
  17.     /**
  18.      * @param hashTable: A list of The first node of linked list
  19.      * @return: A list of The first node of linked list which have twice size
  20.      */   
  21.     vector<ListNode*> rehashing(vector<ListNode*> hashTable) {
  22.         int n1 = hashTable.size();
  23.         int n2 = n1 * 2;
  24.         vector<ListNode *> ans(n2, NULL);
  25.         vector<ListNode *> tail(n2, NULL);
  26.         
  27.         int i, j;
  28.         ListNode *p, *q;
  29.         for (i = 0; i < n1; ++i) {
  30.             p = hashTable[i];
  31.             while (p != NULL) {
  32.                 q = p->next;
  33.                 j = addr(p->val, n2);
  34.                
  35.                 if (ans[j] == NULL) {
  36.                     ans[j] = tail[j] = p;
  37.                 } else {
  38.                     tail[j]->next = p;
  39.                     tail[j] = p;
  40.                 }
  41.                 tail[j]->next = NULL;
  42.                
  43.                 p = q;
  44.             }
  45.             hashTable[i] = NULL;
  46.         }
  47.         return ans;
  48.     }
  49. private:
  50.     int addr(int val, int cap) {
  51.         return val >= 0 ? val % cap : (val % cap + cap) % cap;
  52.     }
  53. };
复制代码
复杂度:时间O(N),空间O(N)。
回复

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-22 04:44:25 | 只看该作者
全局:
又被吞掉一题:Rehashing。
回复

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-22 04:49:12 | 只看该作者
全局:
Heapify
题意:建堆。
解法:自底向上逐步筛选、交换。
代码:
  1. #include <algorithm>
  2. using namespace std;

  3. class Solution {
  4. public:
  5.     /**
  6.      * @param A: Given an integer array
  7.      * @return: void
  8.      */
  9.     void heapify(vector<int> &A) {
  10.         int n = A.size();
  11.         if (n < 2) {
  12.             return;
  13.         }
  14.         int i, j, k;
  15.         int minVal;
  16.         
  17.         for (i = (n - 1) / 2; i >= 0; --i) {
  18.             j = i;
  19.             while (j * 2 + 1 <= n - 1) {
  20.                 k = j;
  21.                 minVal = A[j];
  22.                 if (A[j * 2 + 1] < minVal) {
  23.                     k = j * 2 + 1;
  24.                     minVal = A[k];
  25.                 }
  26.                 if (j * 2 + 2 <= n - 1 && A[j * 2 + 2] < minVal) {
  27.                     k = j * 2 + 2;
  28.                     minVal = A[k];
  29.                 }
  30.                 if (k == j) {
  31.                     break;
  32.                 }
  33.                 swap(A[j], A[k]);
  34.                 j = k;
  35.             }
  36.         }
  37.     }
  38. };
复制代码
复杂度:时间O(N),空间O(1)。
回复

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-22 04:55:29 | 只看该作者
全局:
Word Search II
题意:hard难度。给定一个字符矩阵,和一个词典。允许你上下左右走,从矩阵的一点走到另一点。请问总共有多少种走法,使得轨迹恰好构成词典里的单词。把那些单词找出来。
解法:和Word Search类似,不过这次有了许多单词,而且要求都找出来,那么首先要考虑的就是DFS的效率问题。于是,为了优化效率,我们引入字典树。代码虽然复杂了,但思路还是比较简单的,就是DFS。
代码:
  1. typedef struct TrieNode {
  2.     static const int N = 26;
  3.    
  4.     bool isWord;
  5.     vector<TrieNode *> child;
  6.    
  7.     TrieNode() {
  8.         isWord = false;
  9.         child.resize(N, NULL);
  10.     }
  11. } TrieNode;

  12. class Solution {
  13. public:
  14.     Solution() {
  15.         d.resize(4, vector<int>(2));
  16.         d[0][0] = +1;
  17.         d[0][1] = 0;
  18.         
  19.         d[1][0] = -1;
  20.         d[1][1] = 0;
  21.         
  22.         d[2][0] = 0;
  23.         d[2][1] = +1;
  24.         
  25.         d[3][0] = 0;
  26.         d[3][1] = -1;
  27.     }
  28.     /**
  29.      * @param board: A list of lists of character
  30.      * @param words: A list of string
  31.      * @return: A list of string
  32.      */
  33.     vector<string> wordSearchII(vector<vector<char> > &board, vector<string> &words) {
  34.         v.clear();
  35.         us.clear();
  36.         ans.clear();
  37.         
  38.         vector<vector<char> > &b = board;
  39.         n = b.size();
  40.         m = n ? b[0].size() : 0;
  41.         if (!(n || m)) {
  42.             return ans;
  43.         }
  44.         
  45.         TrieNode *root = new TrieNode();
  46.         for (auto it = words.begin(); it != words.end(); ++it) {
  47.             insertWord(root, *it);
  48.         }
  49.         
  50.         string s = "";
  51.         v.resize(n, vector<bool>(m, false));
  52.         int i, j;
  53.         for (i = 0; i < n; ++i) {
  54.             for (j = 0; j < m; ++j) {
  55.                 v[i][j] = true;
  56.                 s.push_back(b[i][j]);
  57.                 DFS(i, j, s, root->child[b[i][j] - 'a'], b);
  58.                 s.pop_back();
  59.                 v[i][j] = false;
  60.             }
  61.         }
  62.         
  63.         for (auto it = us.begin(); it != us.end(); ++it) {
  64.             ans.push_back(*it);
  65.         }
  66.         clearTrie(root);
  67.         return ans;
  68.     }
  69. private:
  70.     int n, m;
  71.     vector<vector<bool> > v;
  72.     unordered_set<string> us;
  73.     vector<string> ans;
  74.     vector<vector<int> > d;
  75.    
  76.     bool inbound(int x, int y) {
  77.         return x >= 0 && x <= n - 1 && y >= 0 && y <= m - 1;
  78.     }
  79.    
  80.     void DFS(int x, int y, string &s, TrieNode *r, vector<vector<char> > &b) {
  81.         if (r == NULL) {
  82.             return;
  83.         }
  84.         if (r->isWord) {
  85.             // A word is found
  86.             us.insert(s);
  87.         }
  88.         int x1, y1;
  89.         int i;
  90.         for (i = 0; i < 4; ++i) {
  91.             x1 = x + d[i][0];
  92.             y1 = y + d[i][1];
  93.             if (!inbound(x1, y1) || v[x1][y1]) {
  94.                 continue;
  95.             }
  96.             v[x1][y1] = true;
  97.             s.push_back(b[x1][y1]);
  98.             DFS(x1, y1, s, r->child[b[x1][y1] - 'a'], b);
  99.             s.pop_back();
  100.             v[x1][y1] = false;
  101.         }
  102.     }
  103.    
  104.     void insertWord(TrieNode *root, string s) {
  105.         int n = s.length();
  106.         if (n == 0) {
  107.             return;
  108.         }
  109.         int i;
  110.         TrieNode *p = root;
  111.         for (i = 0; i < n; ++i) {
  112.             if (p->child[s[i] - 'a'] == NULL) {
  113.                 p->child[s[i] - 'a'] = new TrieNode();
  114.             }
  115.             p = p->child[s[i] - 'a'];
  116.         }
  117.         p->isWord = true;
  118.     }
  119.    
  120.     void clearTrie(TrieNode *&root) {
  121.         if (root == NULL) {
  122.             return;
  123.         }
  124.         int i;
  125.         for (i = 0; i < TrieNode::N; ++i) {
  126.             clearTrie(root->child[i]);
  127.         }
  128.         root->child.clear();
  129.         delete root;
  130.         root = NULL;
  131.     }
  132. };
复制代码
复杂度:时间O((N * M)!),空间一样。

补充内容 (2015-7-23 15:11):
更正:复杂度:时间O(4 ^ (N * M)),空间一样。只是理论复杂度很高,实际当然没这么高。
回复

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-22 05:10:33 | 只看该作者
全局:
LRU Cache
题意:hard难度。实现一个LRU Cache。
解法:哈希表配合双向链表,所有操作都可以O(1)时间完成。此题很容易一堆bug,因为双链表比单链表还乱。
代码:
  1. // Hashmap and doubly linked list.
  2. #include <unordered_map>
  3. using namespace std;

  4. typedef struct DoublyListNode {
  5.     int key;
  6.     int val;
  7.     struct DoublyListNode *left;
  8.     struct DoublyListNode *right;
  9.     DoublyListNode(int key = 0, int val = 0): key(key), val(val) {
  10.         left = right = NULL;
  11.     }
  12. } DLN;

  13. class LRUCache{
  14. public:
  15.     // @param capacity, an integer
  16.     LRUCache(int capacity) {
  17.         cap = capacity;
  18.         size = 0;
  19.         head = tail = NULL;
  20.     }
  21.    
  22.     // @return an integer
  23.     int get(int key) {
  24.         if (um.find(key) == um.end()) {
  25.             return DEFAULT_VALUE;
  26.         }
  27.         moveToFront(key);
  28.         return um[key]->val;
  29.     }

  30.     // @param key, an integer
  31.     // @param value, an integer
  32.     // @return nothing
  33.     void set(int key, int value) {
  34.         DLN *p;
  35.         if (um.find(key) == um.end()) {
  36.             if (size == cap) {
  37.                 p = tail;
  38.                 um.erase(tail->key);
  39.                 tail->key = key;
  40.                 tail->val = value;
  41.             } else {
  42.                 p = new DLN(key, value);
  43.                 if (head == NULL) {
  44.                     head = tail = p;
  45.                 } else {
  46.                     p->right = head;
  47.                     head->left = p;
  48.                     head = p;
  49.                 }
  50.                 ++size;
  51.             }
  52.             um[key] = p;
  53.         } else {
  54.             p = um[key];
  55.             p->val = value;
  56.         }
  57.         moveToFront(key);
  58.     }
  59. private:
  60.     static const int DEFAULT_VALUE = -1;
  61.     unordered_map<int, DLN *> um;
  62.     int cap;
  63.     int size;
  64.     DLN *head, *tail;
  65.    
  66.     void moveToFront(int key) {
  67.         if (um.find(key) == um.end()) {
  68.             return;
  69.         }
  70.         DLN *p = um[key];
  71.         if (p == head) {
  72.             return;
  73.         }
  74.         
  75.         if (p == tail) {
  76.             tail = tail->left;
  77.             tail->right = NULL;
  78.         } else {
  79.             p->left->right = p->right;
  80.             p->right->left = p->left;
  81.         }
  82.         p->left = NULL;
  83.         p->right = head;
  84.         head->left = p;
  85.         head = p;
  86.     }
  87. };
复制代码
复杂度:时间各种O(1),空间各种O(1)。全局空间开销O(N)。
回复

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-22 05:22:32 | 只看该作者
全局:
Combination Sum
题意:给定一个数组A和整数target。数组中每个元素可以取无数次,求所有加起来等于target的组合。
解法:DFS,注意剪剪枝。
代码:
  1. #include <algorithm>
  2. #include <unordered_set>
  3. using namespace std;

  4. class Solution {
  5. public:
  6.     /**
  7.      * @param candidates: A list of integers
  8.      * @param target:An integer
  9.      * @return: A list of lists of integers
  10.      */
  11.     vector<vector<int> > combinationSum(vector<int> &candidates, int target) {
  12.         v.clear();
  13.         us.clear();
  14.         a.clear();
  15.         ans.clear();
  16.         
  17.         n = candidates.size();
  18.         int i;
  19.         for (i = 0; i < n; ++i) {
  20.             us.insert(candidates[i]);
  21.         }
  22.         for (auto it = us.begin(); it != us.end(); ++it) {
  23.             a.push_back(*it);
  24.         }
  25.         n = a.size();
  26.         sort(a.begin(), a.end());
  27.         t = target;
  28.         DFS(0, 0);
  29.         return ans;
  30.     }
  31. private:
  32.     vector<int> v;
  33.     unordered_set<int> us;
  34.     vector<int> a;
  35.     vector<vector<int> > ans;
  36.     int n;
  37.     int t;
  38.    
  39.     void DFS(int idx, int sum) {
  40.         if (sum == t) {
  41.             ans.push_back(v);
  42.             return;
  43.         }
  44.         if (idx == n) {
  45.             return;
  46.         }
  47.         if (sum + a[idx] > t) {
  48.             return;
  49.         }
  50.         int i = 0;
  51.         int j;
  52.         while (sum + i * a[idx] <= t) {
  53.             for (j = 0; j < i; ++j) {
  54.                 v.push_back(a[idx]);
  55.             }
  56.             DFS(idx + 1, sum + i * a[idx]);
  57.             for (j = 0; j < i; ++j) {
  58.                 v.pop_back();
  59.             }
  60.             ++i;
  61.         }
  62.     }
  63. };
复制代码
复杂度:式子比较长,不好写。
回复

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-22 05:26:02 | 只看该作者
全局:
本帖最后由 zhuli19901106 于 2015-7-22 05:29 编辑

Palindrome Partitioning
题意:给定一个字符串,可以把它分割成回文子串之和。请求出所有不同的分割方法。
解法:首先用O(N ^ 2)时间和空间求出所有字串是否是回文串,然后进行DFS。
代码:
  1. class Solution {
  2. public:
  3.     /**
  4.      * @param s: A string
  5.      * @return: A list of lists of string
  6.      */
  7.     vector<vector<string> > partition(string s) {
  8.         pal.clear();
  9.         ans.clear();
  10.         n = s.length();
  11.         if (n == 0) {
  12.             return ans;
  13.         }
  14.         
  15.         pal.resize(n, vector<bool>(n, false));
  16.         int i, j;
  17.         for (i = 0; i < n; ++i) {
  18.             pal[i][i] = true;
  19.         }
  20.         for (i = 0; i < n - 1; ++i) {
  21.             pal[i][i + 1] = (s[i] == s[i + 1]);
  22.         }
  23.         for (i = 2; i < n; ++i) {
  24.             for (j = 0; j + i < n; ++j) {
  25.                 pal[j][j + i] = (s[j] == s[j + i]) && pal[j + 1][j + i - 1];
  26.             }
  27.         }
  28.         vector<string> par;
  29.         DFS(s, par, 0);
  30.         
  31.         return ans;
  32.     }
  33. private:
  34.     int n;
  35.     vector<vector<bool> > pal;
  36.     vector<vector<string> > ans;
  37.    
  38.     void DFS(string &s, vector<string> &par, int idx) {
  39.         if (idx == n) {
  40.             ans.push_back(par);
  41.             return;
  42.         }
  43.         int i;
  44.         for (i = n - 1; i >= idx; --i) {
  45.             if (!pal[idx][i]) {
  46.                 continue;
  47.             }
  48.             par.push_back(s.substr(idx, i - idx + 1));
  49.             DFS(s, par, i + 1);
  50.             par.pop_back();
  51.         }
  52.     }
  53. };
复制代码
复杂度:O(N!),空间一样。

回复

使用道具 举报

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

本版积分规则

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