1.504. Base 7
水题,直接写。但是我错了一次,忘了处理0的情况。 没有考虑边界条件。写完代码,一般需要自己想几个边界测试用例进行测试。
1 class Solution { 2 public: 3 string convertTo7(int num) { 4 if(num == 0) return "0"; 5 int a = abs(num); 6 string res; 7 while(a) { 8 int t = a % 7; 9 a /= 7; 10 res += char(t + '0'); 11 } 12 if(num < 0) 13 res += "-"; 14 reverse(res.begin(), res.end()); 15 return res; 16 17 } 18 };
上面的abs好像没考虑最大的负数溢出问题,注意!题目数据范围小!
2. 513. Find Left Most Element
水题吧,记录一下,每一层的起始元素,返回最后一层的起始值。
1 /** 2 * Definition for a binary tree node. 3 * struct TreeNode { 4 * int val; 5 * TreeNode *left; 6 * TreeNode *right; 7 * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 8 * }; 9 */ 10 class Solution { 11 public: 12 int findLeftMostNode(TreeNode* root) { 13 queue<TreeNode*> q; 14 q.push(root); 15 int res = root->val; 16 while(!q.empty()) { 17 int sz = q.size(); 18 res = q.front()->val; 19 while(sz--) { 20 TreeNode* t = q.front(); 21 q.pop(); 22 if(t->left) q.push(t->left); 23 if(t->right) q.push(t->right); 24 } 25 } 26 return res; 27 } 28 };
3. 515. Find Largest Element in Each Row
跟第二题一样,也算水题吧,每一层求解一下最大值。
1 /** 2 * Definition for a binary tree node. 3 * struct TreeNode { 4 * int val; 5 * TreeNode *left; 6 * TreeNode *right; 7 * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 8 * }; 9 */ 10 class Solution { 11 public: 12 vector<int> findValueMostElement(TreeNode* root) { 13 vector<int> res; 14 if(!root) return res; 15 queue<TreeNode*> q; 16 q.push(root); 17 while(!q.empty()) { 18 int sz = q.size(); 19 int d = INT_MIN; 20 while(sz--) { 21 TreeNode* t = q.front(); 22 q.pop(); 23 d = max(d, t->val); 24 if(t->left) q.push(t->left); 25 if(t->right) q.push(t->right); 26 } 27 res.push_back(d); 28 } 29 return res; 30 } 31 };
4. 493. Reverse Pairs
原题,你一定做过求逆序对的题目,就跟这个一模一样。但是,我还是花了一些时间。依稀记得,这道题,我是原模原样见过,在上算法课的时候,老师讲divide and conquer的作业题,我记得我做错了,当时差不多搞懂了,现在又不会了!还是当初没搞懂啊!
一种解法是mergesort,在merge的时候,求解个数,求逆序对很容易计算,跟排序的循环一起,但是这道题目就不一样,需要单独的循环计算这个特别的逆序对。在开启一个循环计算,复杂对一样,只是增加了一些系数的时间。
另一种解法是树状数组,(当然,线段树也可以),按顺序插入一个数,记当前数为a[i],统计大于2*a[i]的元素的个数,然后插入a[i]. 插入和计数可以用树状数组高效的维护。需要注意(看的第一名大神的写法):树状数组的下标非负,这题数据有负数,还有数据范围很大,需要离散化处理,但是,又有二倍的数,不好处理,可以使用map,负数的下标加上一个base偏移来解决。 这题的数据很大,二倍的数据会溢出int,算是一个很大的坑吧! 题目做的多了,应该一眼就能看到这题的考点,数据溢出!看前面的神牛,就一次没有错!
贴上我写的代码,(写的不是很好,可以参考排名靠前大神们的代码):
mergesort:
1 typedef long long ll; 2 class Solution { 3 public: 4 int res; 5 vector<int> b; 6 void mg(vector<int> &a, int x, int mid, int y) { 7 8 9 int i = x, j = mid + 1; 10 int p = x; 11 for (int k = 0; k < y - x + 1; k++) { 12 if(i > mid) { 13 b[p] = a[j]; 14 j++; p++; 15 continue; 16 } 17 if(j > y) { 18 b[p] = a[i]; 19 p++; 20 i++; 21 continue; 22 } 23 if(a[i] <= a[j]) { 24 b[p] = a[i]; 25 i++; p++; 26 } else { 27 b[p] = a[j]; 28 p++; j++; 29 } 30 } 31 i = x; j = mid + 1; 32 for (int k = 0; k < y - x + 1; k++) { 33 if(i > mid) break; 34 if(j > y) break; 35 ll td = a[j]; 36 if(a[i] > 2 * td) { 37 res += (mid + 1 - i); 38 j++; 39 } else i++; 40 } 41 for (int k = x; k <= y; k++) 42 a[k] = b[k]; 43 } 44 void mergesort(vector<int> &a, int left, int right) { 45 if(left >= right) return; 46 int mid = (left + right) / 2; 47 mergesort(a, left, mid); 48 mergesort(a, mid + 1, right); 49 mg(a, left, mid, right); 50 } 51 int reversePairs(vector<int>& nums) { 52 res = 0; 53 int n = nums.size(); 54 if(n < 2) return res; 55 b = nums; 56 mergesort(nums, 0, n - 1); 57 return res; 58 }
树状数组:
1 typedef long long ll; 2 class Solution { 3 public: 4 int res; 5 map<ll, int> ma; 6 ll base = 1ll << 34; 7 ll lowbit(ll x) { 8 return x & -x; 9 } 10 void add(ll x) { 11 x += base; 12 while(x <= 1ll << 36) { 13 ma[x]++; 14 x += lowbit(x); 15 } 16 } 17 int ask(ll x) { 18 x += base; 19 int res = 0; 20 while(x) { 21 res += ma[x]; 22 x -= lowbit(x); 23 } 24 return res; 25 } 26 int reversePairs2(vector<int>& nums) { 27 res = 0; 28 int n = nums.size(); 29 if(n < 2) return res; 30 ma.clear(); 31 for (int i = n - 1; i >= 0; i--) { 32 res += ask(nums[i] - 1ll); 33 add(2ll * nums[i]); 34 } 35 return res; 36 }