1. 507. Perfect Number
显然小于2的都不满足(尤其是负数的情况),进一步,显然质数都不满足,所以小于4的数,直接return false。
然后依次暴力枚举判断到sqrt(n),注意n = t * t的时候,t只需要加一次。好像不写这个也不会出错,因为没有这样的数满足条件。我没验证,需要的验证一下。
1 class Solution { 2 public: 3 bool checkPerfectNumber(int num) { 4 if(num <= 1) return 0; 5 int res = 1; 6 int d = floor(sqrt(num)); 7 for (int i = 2; i <= d; i++) { 8 if(i == num) break; 9 if(num % i == 0) {10 res += i;11 if(i != num / i) res += num / i;12 if(res > num) return 0;13 }14 }15 return res == num;16 }17 };
2. 537. Complex Number Multiplication
按照题意完成就可以。
1 class Solution { 2 public: 3 string complexNumberMultiply(string a, string b) { 4 int x = 0, y = 0, m = 0, n = 0; 5 sscanf(a.c_str(), "%d+%di", &x, &y); 6 sscanf(b.c_str(), "%d+%di", &m, &n); 7 stringstream ss; 8 int t1 = x * m - y * n, t2 = x * n + y * m; 9 ss << t1 << "+" << t2 << "i";10 return ss.str();11 }12 };
3. 545. Boundary of Binary Tree
左扫一遍,叶子扫一遍,右边扫一遍,注意边界条件。编码比较多,注意特判。
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 res;13 vector ri;14 bool f;15 void workleft(TreeNode* root) {16 if(!root) return;17 res.push_back(root->val);18 if(root->left)19 workleft(root->left);20 else21 workleft(root->right);22 }23 void work(TreeNode* root) {24 if(!root) return;25 if(!root->left && !root->right) {26 if(!f) f = 1;27 else res.push_back(root->val);28 }29 work(root->left);30 work(root->right);31 }32 void workright(TreeNode* root) {33 if(!root) return;34 ri.push_back(root->val);35 if(root->right)36 workright(root->right);37 else38 workright(root->left);39 }40 vector boundaryOfBinaryTree(TreeNode* root) {41 res.clear();42 if(!root) return res;43 res.push_back(root->val);44 workleft(root->left);45 if(root->left)46 f = 0;47 else48 f = 1;49 work(root->left);50 work(root->right);51 ri.clear();52 workright(root->right);53 reverse(ri.begin(), ri.end());54 //cout << res.size() << " " << ri.size() << endl;55 for (int i = 1; i < ri.size(); i++) {56 res.push_back(ri[i]);57 //cout << ri[i] << endl;58 }59 return res;60 }61 };
4. 546. Remove Boxes
不会做,没有想法。看完题目,感觉跟burst ballon挺像的,因为枚举先删除的话,左右2边的会合在一起,使得后续的处理边的麻烦,应该是需要最后考虑,怎么进行合并,使得2边的问题变得独立。
从discuss里面看的答案。好像先把数组处理成字符,个数的形式,不是很好处理,需要寻找一种好的枚举方法,对问题进行化简。
刚开始,观察,如果一个字符只出现一次,那么这个字符对结果的贡献就是1,也就是说可以直接删除它,删除后左右2边的部分进行合并,这里有个问题,这个单独字符删除的时间,是否会影响最后的结果,不太确定。
我的想法是,处理成数字,个数的形式,然后依次枚举删除的字符。每次调用的时候,先进行单个字符的处理,然后合并相邻的,再递归调用,结果是tle。完全是暴力的解法。
下面的解法是,每次处理末尾的字符,使得问题规模缩小,然后考虑末尾的字符,可能跟前面的字符进行合并,然后进行搜索,有些段可能多次计算,采用记忆化搜索。这个想法的关键是,找到一种搜索的办法,缩减问题规模,同时不遗漏可能的解。
1 int dp[110][110][110]; 2 int work(vector & b, int l, int r, int k) { 3 if(l > r) return 0; 4 int& res = dp[l][r][k]; 5 if(res != 0) return res; 6 while(l < r && b[r - 1] == b[r]) { 7 k++; 8 r--; 9 }10 res = work(b, l, r - 1, 0) + (k + 1) * (k + 1);11 for (int i = l; i < r; i++) {12 if(b[i] == b[r]) {13 res = max(res, work(b, l, i, k + 1) + work(b, i + 1, r - 1, 0));14 }15 }16 return res;17 }18 int removeBoxes(vector & boxes) {19 memset(dp, 0, sizeof dp);20 int n = boxes.size();21 return work(boxes, 0, n - 1, 0);22 }