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

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

 
🔗
 楼主| zhuli19901106 2015-7-23 21:34:55 | 只看该作者
全局:
Update Bits
题意:给定整数N和M,请把M插到N的i~j位去。
解法:既然指明了是位操作,那这题就不要用循环。
代码:
  1. class Solution {
  2. public:
  3.     /**
  4.      *@param n, m: Two integer
  5.      *@param i, j: Two bit positions
  6.      *return: An integer
  7.      */
  8.     int updateBits(int n, int m, int i, int j) {
  9.         if (i == 0 && j == 31) {
  10.             return m;
  11.         }
  12.         return (~(((1 << (j - i + 1)) - 1) << i) & n) | (m << i);
  13.     }
  14. };
复制代码
复杂度:时间O(1),空间O(1)。
回复

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-23 21:47:25 | 只看该作者
全局:
Binary Representation
题意:hard难度。
解法:这题可以说是POJ1331和POJ1220的综合,考察数制转换。整数和小数部分的做法不一样。整数按照除2取余,小数按照乘2取整。我不知道这题的hard难度主要体现在哪,不过从写代码写得磕磕绊绊的过程看来,估计这题确实不算简单吧。
代码:
  1. // What a mess...
  2. #include <cstdlib>
  3. using namespace std;

  4. typedef long long int LL;
  5. class Solution {
  6. public:
  7.     /**
  8.      *@param n: Given a decimal number that is passed in as a string
  9.      *@return: A string
  10.      */
  11.     string binaryRepresentation(string n) {
  12.         string s = "";
  13.         int len = n.length();
  14.         int dp;
  15.         for (dp = 0; dp < len; ++dp) {
  16.             if (n[dp] == '.') {
  17.                 break;
  18.             }
  19.         }
  20.         
  21.         int i = 0;
  22.         LL num = 0;
  23.         for (i = 0; i < dp; ++i) {
  24.             num = num * 10 + (n[i] - '0');
  25.             if (num > (1LL << 32) - 1) {
  26.                 return "ERROR";
  27.             }
  28.         }
  29.         while (num != 0) {
  30.             s.push_back((num & 1) + '0');
  31.             num >>= 1;
  32.         }
  33.         if (s.length() == 0) {
  34.             s = "0";
  35.         }
  36.         reverse(s.begin(), s.end());
  37.         
  38.         double d = atof(n.substr(dp, len - dp).data());
  39.         if (dp == len || d <= EPS) {
  40.             return s.length() <= 32 ? s : "ERROR";
  41.         }
  42.         s.push_back('.');
  43.         
  44.         string f = "";
  45.         for (i = dp + 1; i < len; ++i) {
  46.             f.push_back(n[i] - '0');
  47.         }
  48.         
  49.         while (f.length() > 0) {
  50.             if (f[0] >= 5) {
  51.                 f[0] -= 5;
  52.                 s.push_back('1');
  53.             } else {
  54.                 s.push_back('0');
  55.             }
  56.             for (i = f.length() - 1; i >= 0; --i) {
  57.                 f[i] *= 2;
  58.             }
  59.             for (i = f.length() - 1; i > 0; --i) {
  60.                 f[i - 1] += f[i] / 10;
  61.                 f[i] %= 10;
  62.             }
  63.             while (!f.empty() && f.back() == 0) {
  64.                 f.pop_back();
  65.             }
  66.             if (s.length() > 64) {
  67.                 // There is a bug here, but my code passed.
  68.                 return "ERROR";
  69.             }
  70.         }
  71.         return s;
  72.     }
  73. private:
  74.     const double EPS = 1e-3;
  75. };
复制代码
复杂度:时间O(N ^ 2),空间O(N)。
回复

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-23 21:51:11 | 只看该作者
全局:
Flip Bits
题意:给定两个32位整数,求把一个变成另一个,需要改变多少位。
解法:异或,数1的个数。
代码:
  1. class Solution {
  2. public:
  3.     /**
  4.      *@param a, b: Two integer
  5.      *return: An integer
  6.      */
  7.     int bitSwapRequired(int a, int b) {
  8.                 a ^= b;
  9.                 int c = 0;
  10.                 while (a) {
  11.                         a = a & a - 1;
  12.                         ++c;
  13.                 }
  14.                 return c;
  15.     }
  16. };
复制代码
复杂度:时间O(log(N)),空间O(1)。
回复

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-23 21:57:10 | 只看该作者
全局:
Delete Digits
题意:有一个N位的正整数,现在要你从中删除掉K位,剩下的数字相对顺序不变。求能够组成的最小整数。
解法:这题有意思,我想了好一会儿都没思路。后来找到了这么个思路:1. 留下的数字当然越小越好。2. 高位的权重比低位要大,所以越是高位,越要尽量小。那么得到的就是一个贪婪的思路。其余细节,参见下面代码。
代码:
  1. class Solution {
  2. public:
  3.     /**
  4.      *@param A: A positive integer which has N digits, A is a string.
  5.      *@param k: Remove k digits.
  6.      *@return: A string
  7.      */
  8.     string DeleteDigits(string A, int k) {
  9.         string ans = "";
  10.         int n = A.length();
  11.         int c = n - k;
  12.         int i, j;
  13.         
  14.         i = 0;
  15.         while (i < n) {
  16.             j = i + 1;
  17.             while (j < n && k > 0) {
  18.                 if (A[j] >= A[i]) {
  19.                     ++j;
  20.                     continue;
  21.                 }
  22.                 if (k >= j - i) {
  23.                     k -= j - i;
  24.                     i = j;
  25.                 }
  26.                 ++j;
  27.             }
  28.             ans.push_back(A[i++]);
  29.             if (ans.length() >= c) {
  30.                 break;
  31.             }
  32.         }
  33.         i = 0;
  34.         while (i < c - 1 && ans[i] == '0') {
  35.             ++i;
  36.         }
  37.         ans = ans.substr(i, c - i);
  38.         return ans;
  39.     }
  40. };
复制代码
复杂度:时间O(N),空间O(1)。
回复

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-23 22:02:29 | 只看该作者
全局:
Wood Cut
题意:给定N根木条,长度不尽相同。现在你从这些木条中切出K根长度一样的。请问每根木条的最大长度。已知切割只能精确到整数,而且只能切不能拼。
解法:二分法。我本来没什么思路,以为这题有很巧妙的解法,后来看了题目下面的复杂度提示,就写了个二分。
代码:
  1. #include <algorithm>
  2. using namespace std;

  3. typedef long long int LL;

  4. class Solution {
  5. public:
  6.     /**
  7.      *@param L: Given n pieces of wood with length L[i]
  8.      *@param k: An integer
  9.      *return: The maximum length of the small pieces.
  10.      */
  11.     int woodCut(vector<int> L, int k) {
  12.         LL ll, rr, mm;
  13.         int n = L.size();
  14.         int i;
  15.         ll = 1;
  16.         rr = 0;
  17.         for (i = 0; i < n; ++i) {
  18.             rr = max(rr, (LL)L[i]);
  19.         }
  20.         if (calc(L, ll) < k) {
  21.             return 0;
  22.         }
  23.         if (calc(L, rr) >= k) {
  24.             return rr;
  25.         }
  26.         while (rr - ll > 1) {
  27.             mm = ll + (rr - ll) / 2;
  28.             if (calc(L, mm) >= k) {
  29.                 ll = mm;
  30.             } else {
  31.                 rr = mm;
  32.             }
  33.         }
  34.         return ll;
  35.     }
  36. private:
  37.     LL calc(vector<int> &L, LL len) {
  38.         int n = L.size();
  39.         int i;
  40.         LL sum = 0;
  41.         for (i = 0; i < n; ++i) {
  42.             sum += L[i] / len;
  43.         }
  44.         return sum;
  45.     }
  46. };
复制代码
复杂度:时间O(N * log(Len)),空间O(log(Len))。
回复

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-23 22:21:02 | 只看该作者
全局:
Largest Number
题意:给定一些整数,把它们首尾相连起来,求能得到的最大整数。
解法:自定义排序。效率应该还可以更优,不过这个解法简洁易懂,所以比较推荐。
代码:
  1. #include <algorithm>
  2. using namespace std;

  3. bool comp(const string &s1, const string &s2)
  4. {
  5.     return s1 + s2 > s2 + s1;
  6. }

  7. class Solution {
  8. public:
  9.     /**
  10.      *@param num: A list of non negative integers
  11.      *@return: A string
  12.      */
  13.     string largestNumber(vector<int> &num) {
  14.         int n = num.size();
  15.         int i;
  16.         vector<string> a;
  17.         for (i = 0; i < n; ++i) {
  18.             a.push_back(to_string(num[i]));
  19.         }
  20.         sort(a.begin(), a.end(), comp);
  21.         i = 0;
  22.         while (i < n - 1 && a[i] == "0") {
  23.             ++i;
  24.         }
  25.         string ans = "";
  26.         while (i < n) {
  27.             ans += a[i++];
  28.         }
  29.         return ans;
  30.     }
  31. };
复制代码
复杂度:时间O(N * log(N)),空间O(N)。
回复

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-23 22:23:07 | 只看该作者
全局:
Matrix Zigzag Traversal
题意:按照反对角线的Z字形方向逐个访问一个二维数组。
解法:按题意做。
代码:
  1. class Solution {
  2. public:
  3.     /**
  4.      * @param matrix: a matrix of integers
  5.      * @return: a vector of integers
  6.      */
  7.     vector<int> printZMatrix(vector<vector<int> > &matrix) {
  8.         vector<int> ans;
  9.         int n, m;
  10.         n = matrix.size();
  11.         if (n == 0) {
  12.             return ans;
  13.         }
  14.         m = matrix[0].size();
  15.         if (m == 0) {
  16.             return ans;
  17.         }
  18.         int i, j;
  19.         int f = 0;
  20.         for (i = 0; i <= n + m - 2; ++i) {
  21.             if (f) {
  22.                 for (j = i; j >= 0; --j) {
  23.                     if (i - j < 0 || i - j > n - 1) {
  24.                         continue;
  25.                     }
  26.                     if (j < 0 || j > m - 1) {
  27.                         continue;
  28.                     }
  29.                     ans.push_back(matrix[i - j][j]);
  30.                 }
  31.             } else {
  32.                 for (j = 0; j <= i; ++j) {
  33.                     if (i - j < 0 || i - j > n - 1) {
  34.                         continue;
  35.                     }
  36.                     if (j < 0 || j > m - 1) {
  37.                         continue;
  38.                     }
  39.                     ans.push_back(matrix[i - j][j]);
  40.                 }
  41.             }
  42.             f = !f;
  43.         }
  44.         return ans;
  45.     }
  46. };
复制代码
复杂度:时间O(N * M),空间O(1)。
回复

使用道具 举报

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

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-23 23:13:21 | 只看该作者
全局:
Gas Station
题意:环形路上有N个加油站的位置,在每个加油站可以加油,在路上要耗油。如果允许你从任一加油站出发,从哪个出发能走完全程?
解法:O(N ^ 2)的做法就不提了。这题的O(N)做法需要理解一个道理:如果我从位置i出发,发现走到j的时候汽油变负数了(也就是走不到)。那么i~j-1必然都不可行。想想为什么?
代码:
  1. class Solution {
  2. public:
  3.     /**
  4.      * @param gas: a vector of integers
  5.      * @param cost: a vector of integers
  6.      * @return: an integer
  7.      */
  8.     int canCompleteCircuit(vector<int> &gas, vector<int> &cost) {
  9.                 int n = gas.size();
  10.                 int i;
  11.                 int sum = 0;
  12.                 int j = 0;
  13.                 for (i = 0; i < 2 * n - 1; ++i) {
  14.                         sum += gas[i % n] - cost[i % n];
  15.                         if (sum < 0) {
  16.                                 sum = 0;
  17.                                 j = i + 1;
  18.                         }
  19.                         if (i - j == n - 1) {
  20.                                 return j;
  21.                         }
  22.                 }
  23.                 return -1;
  24.     }
  25. };
复制代码
复杂度:时间O(N),空间O(1)。
回复

使用道具 举报

🔗
 楼主| zhuli19901106 2015-7-23 23:34:44 | 只看该作者
全局:
Maximum Product Subarray
题意:给定一个数组,求出乘积最大的子数组。
解法:这题我起初还考虑正数负数和0,后来发现想复杂了。因为负数会导致变号,所以我同时保存最大乘积跟最小乘积。这样就能写出比较简单的解法了。
代码:
  1. #include <algorithm>
  2. using namespace std;

  3. class Solution {
  4. public:
  5.     /**
  6.      * @param nums: a vector of integers
  7.      * @return: an integer
  8.      */
  9.     int maxProduct(vector<int>& nums) {
  10.         int n = nums.size();
  11.         if (n == 0) {
  12.             return 0;
  13.         }
  14.         
  15.         int mm, MM;
  16.         int mm1, MM1;
  17.         int ans;
  18.         
  19.         ans = mm = MM = nums[0];
  20.         int i;
  21.         for (i = 1; i < n; ++i) {
  22.             mm1 = min(nums[i], min(nums[i] * mm, nums[i] * MM));
  23.             MM1 = max(nums[i], max(nums[i] * mm, nums[i] * MM));
  24.             mm = mm1;
  25.             MM = MM1;
  26.             ans = max(ans, MM);
  27.         }
  28.         return ans;
  29.     }
  30. };
复制代码
复习度:时间O(N),空间O(1)。
回复

使用道具 举报

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

本版积分规则

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