int numJewelsInStones(string J, string S) {
int count = 0;
for (char c : J) {
for (char s : S) {
if (c == s) count++;
}
}
return count;
}
但是,题目中说J中字母没有重复的,所以可以先想到用set。
int numJewelsInStones(string J, string S) {
int count = 0;
set<char> setJ(J.begin(),J.end());
for (char c : S) if (setJ.count(c)) count++;
return count;
}
760 Find Anagram Mappings
思路:用hashmap数据结构
class Solution {
public:
vector<int> anagramMappings(vector<int>& A, vector<int>& B) {
vector<int> res;
unordered_map<int,int> map;
for (int i=0;i<B.size();i++) map[B[i]] = i;
for (int i=0;i<A.size();i++) res.push_back(map[A[i]]);
return res;
}
};
461.Hamming Distance
思路1:移位操作,每次和1进行与操作。
class Solution {
public:
int hammingDistance(int x, int y) {
int n = x ^ y;
int count = 0;
while(n){
count += n & 1;
n = n >> 1;
}
return count;
}
};
思路2:位操作中,n&(n-1)的结果是每次把最右边的1给去掉。
class Solution{
public:
int hanmmingDistance(int x,int y){
int n = x ^ y;
int count = 0;
while(n){
count++;
n = n & (n-1);
}
return count;
}
};
657.Judge Route Circle
思路1:判断字符串中的UD个数是否相等,LR个数是否相等。
class Solution {
public:
bool judgeCircle(string moves) {
int udCount = 0;
int lrCount = 0;
for(char ch : moves){
switch(ch){
case 'U':
udCount ++;
break;
case 'D':
udCount --;
break;
case 'R':
lrCount ++;
break;
case 'L':
lrCount --;
break;
}
}
return udCount == 0 && lrCount == 0;
}
};
class Solution {
public:
bool judgeCircle(string moves) {
int lr = 0,ud = 0;
for(char ch:moves){
lr += (ch == 'L') - (ch == 'R');
ud += (ch == 'U') - (ch == 'D');
}
return lr==0 && ud==0;
};
617 Merge Two Binary Trees
这道题用到了递归,被递归虐的酸爽爆了。虽然我们平时很少用递归,但是这个思想还是需要懂得
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) {
if (t1 && t2){
TreeNode* root = new TreeNode(t1->val + t2->val);
root->left = mergeTrees(t1->left,t2->left);
root->right = mergeTrees(t1->right,t2->right);
return root;
} else {
return t1 ? t1 : t2;
}
}
};
728 Self Dividing Numbers
思路一:首先是判断一个数字num是不是self dividing number,不断取出每一个位数的数,然后取余判断。
然后就是在left和right之间遍历,把符合要求的添加到vector后面。
class Solution {
public:
vector<int> selfDividingNumbers(int left, int right) {
vector<int> res;
for (int i=left; i<=right; i++){
if(dividingNum(i)) res.push_back(i);
}
return res;
}
bool dividingNum(int num){
int temp = num;
while(temp){
int d = temp % 10;
if (d == 0 || num%d > 0 )
return false;
temp = temp / 10;
}
return true;
}
};
思想2:把数字–>character array,修改了dividingNum函数
bool dividingNum(int num){
string num_str = to_string(num);
for (auto c : num_str){
if (c == '0' || num % (c - '0'))
return false;
}
return true;
}
561 Array Partition I
思想:因为找每个数对中最小值,然后求和。所以最大的那个值我们用不到,所以就要得到倒数第二大的数,然后倒数第三大的数也得不到,所以就要得到倒数第四大的数。。。。所以排序后,选择第0,2,4….n-1个数相加,是最大值。
int arrayPairSum(vector<int>& nums){
int sum = 0;
sort(nums.begin(),nums.end());
for (int i = 0; i < nums.size(); i = i + 2) {
sum += nums[i];
}
return sum;
}
476 Number Complement
思路1:求一个数的补数,例如101,求出来是010 = 2,但是如果给的数是0010,不能变成1101,因为必须从第一个非0位开始反转。所以,第一步从左到右找到第一个非0位,第二步就是每一位与1做异或,保证做异或的那一位0变1,1变0;
int findComplement(int num) {
bool flag = false;
for (int i = 31; i >= 0; --i) {
if (num & (1<<i)) flag = true;
if (flag) num = num ^ (1 << i);
}
return num;
}
思路2:因为~就可以把一个数取反,但是不能保证第一位1之前的0不被反转,所以需要一个mask来确定第一个1的位置
int findComplement(int num) {
int mask = INT_MAX;
while (mask & num) mask <<= 1;
return ~mask & ~num;
}
思路3:综合1,2.
int findComplement(int num) {
for (int i = 31; i >= 0; --i) {
if (num & (1<<i)) {
return ~num & (int)(pow(2,i+1)-1);
}
}
}
557 Reverse Words in a String III
思路1:找到空格位置和末尾位置,用reverse函数进行反转。
string reverseWords(string s) {
for (int i = 0;i < s.size(); ++i) {
for (int j = i;j <= s.size(); ++j) {
if (s[j] == ' ' || j == s.size()) {
reverse(s.begin() + i,s.begin() + j);
i = j;
break;
}
}
}
return s;
}
344 Reverse String
思路:就是调换位置,太简单喽。。。。可以直接用STL中的reverse()和swap()
string reverseString(string s) {
reverse(s.begin(),s.end());
return s;
}
string reverseString1(string s) {
int n = s.length();
for (int i = 0; i < n / 2; ++i) {
char temp = s[i];
s[i] = s[n - i - 1];
s[n - i - 1] = temp;
}
return s;
}
string reverseString2(string s) {
int n = s.length();
for (int i = 0; i < n/2; ++i) {
swap(s[i],s[n-i-1]);
}
return s;
}
500 Keyboard Row
思路:
vector<string> findWords(vector<string>& words) {
vector<string> res;
int flags[26] = {1, 0, 0, 1, 2, 1, 1, 1, 2, 1, 1, 1, 0, 0, 2, 2, 2, 2, 1, 2, 2, 0, 2, 0, 2, 0};
for (string word : words) {
int flag = 3;
bool hit = true;
for (char c : word) {
if (flag < 3 && flag != flags[tolower(c) - 'a']) {
hit = false;
break;
}
flag = flags[tolower(c) - 'a'];
}
if (hit) res.push_back(word);
}
return res;
}
vector<string> findWords1(vector<string>& words) {
vector<string> res;
vector<int> flags(26);
vector<string> rows = {"qwertyuiop","asdfghjkl","zxcvbnm"};
for (int i = 0;i < 3; i++) {
for (char c : rows[i]) flags[c - 'a'] = 1 << i;
}
for (string word : words) {
int r = 7;
for (char c : word) {
r &= flags[tolower(c) - 'a'];
if (r == 0) break;
}
if (r) res.push_back(word);
}
return res;
}
682 Baseball Game
思路1:用vector保存每一次的得分,然后就是判断每一次的输入字符是什么。
int calPoints(vector<string>& ops) {
int sum = 0,score = 0;
vector<int> scores;
for (string op : ops) {
if (op == "+") {
score = scores[scores.size()-1] + scores[scores.size()-2];
sum += score;
scores.push_back(score);
}
else if (op == "C") {
sum -= scores.back();
scores.pop_back();
}
else if (op == "D") {
score = scores.back() * 2;
scores.push_back(score);
sum += score;
}
else {
scores.push_back(stoi(op));
sum += scores.back();
}
}
return sum;
}
思路2:更加简练一些
int calPoints(vector<string>& ops) {
vector<int> scores;
for (string op : ops) {
if (op == "C") scores.pop_back();
else if (op == "D") scores.push_back(scores.back() * 2);
else if (op == "+") scores.push_back( ( *(scores.end()-1) ) +( *(scores.end()-2) ) );
else scores.push_back(stoi(op));
}
return accumulate(scores.begin(),scores.end(),0);
}
TreeNode* trimBST(TreeNode* root, int L, int R) {
if (root == NULL) return NULL;
if (root->val < L) return trimBST(root->right,L,R);
if (root->val > R) return trimBST(root->left,L,R);
root->left = trimBST(root->left,L,R);
root->right = trimBST(root->right,L,R);
return root;
}
575 Distribute Candies
思路1:暴力搜索。把vector中数字种类count算出来,然后如果种类小于n/2,那么返回count,如果大于n/2,返回n/2;
int distributeCandies(vector<int>& candies) {
int num = candies.size();
int count = 0;
for (int i = 0;i < num && count < num/2; ++i) {
if (candies[i] != INT_MIN) {
count++;
for (int j = i + 1;j < num; ++j) {
if (candies[j] == candies[i])
candies[j] = INT_MIN;
}
}
}
return count;
}
但是,显示超时,所以这个思路并不好。
思路2:我们还是计算数字种类count,和上个思想相同,但是计算种类的方法我们先把vector进行排序,然后再统计。
int distributeCandies(vector<int>& candies) {
sort(candies.begin(),candies.end());
int num = candies.size();
int count = 1;
for (int i = 1;i < num && count < num/2; ++i) {
if (candies[i] > candies[i-1]) count++;
}
return count;
}
思路3:unordered_set()
int distributeCandies(vector<int>& candies) {
unordered_set<int> kinds;
for (int i = 0;i < candies.size(); ++i) {
kinds.insert(candies[i]);
}
return min(candies.size()/2,kinds.size());
}
412 Fizz Buzz
思路:就是条件判断
vector<string> fizzBuzz(int n) {
vector<string> res;
for (int i = 1;i <= n; i++) {
if (i % 3 == 0 || i % 5 == 0) {
if (i % 3 == 0 && i % 5 == 0) {
res.push_back("FizzBuzz");
}else {
if (i % 3 == 0) res.push_back("Fizz");
else res.push_back("Buzz");
}
}
else {
res.push_back(to_string(i));
}
}
return res;
}
看了一下discuss,把i % 3 == 0 || i % 5 == 0
改成i % 15 == 0
就好了。
463 Island Perimeter
思路:首先是找到数字1的个数oneNum,每个1相当于有4条边,然后确定两个1相邻的情况,找到相邻边,扫描每行和每列,确定有两个相邻的1,那么connection就加1,最后oneNum*4-connection*2.
int islandPerimeter(vector<vector<int>>& grid) {
int connection = 0;
int oneNum = 0;
for (int i = 0; i < grid.size(); i++) {
for (int j = 0; j < grid[0].size(); j++) {
if (grid[i][j] == 1) oneNum++;
if (j != 0 && abs(grid[i][j] - grid[i][j-1]) == 0 && grid[i][j] != 0) connection++;
if (i != 0 && abs(grid[i][j] - grid[i-1][j]) == 0 && grid[i][j] != 0) connection++;
}
}
return oneNum * 4 - connection * 2;
}
思路2:遍历每一行和每一列,有差值就代表是边。最后再加上边框的值。
int islandPerimeter(vector<vector<int>>& grid) {
int sum = 0;
int n = grid.size();
int m = grid[0].size();
for (int i = 0; i < n; i++) {
for (int j = 0; j < m - 1; j++) {
sum += abs(grid[i][j+1] - grid[i][j]);
}
sum += grid[i][0] + grid[i][m-1]; //一定要注意这里的m-1,之前写成了m,调试了半小时
}
for (int j = 0;j < m; j ++) {
for (int i = 0; i < n - 1; i++) {
sum += abs(grid[i+1][j] - grid[i][j]);
}
sum += grid[0][j] + grid[n-1][j];
}
return sum;
}
566 Reshape the Matrix
思路:
- 判断新的shape个数是否匹配
if (m * n != r * c) return nums;
- 如果匹配,说明可以转换。把数都放进一个queue中,再从queue中添加到新的vector中。
vector<vector<int>> matrixReshape(vector<vector<int>>& nums, int r, int c) {
vector<vector<int>> res;
queue<int> temp;
int n = nums.size();
int m = nums[0].size();
if (m * n != r * c) return nums;
else {
for (auto v1 : nums) {
for (auto v2 : v1) {
temp.push(v2);
}
}
for (int i = 0;i < r; i++) {
vector<int> t = {};
for (int j = 0; j < c; j++) {
t.push_back(temp.front());
temp.pop();
}
res.push_back(t);
}
return res;
}
}
思路2:不需要额外空间queue。但是注意要初始化vector<vector<int>> res(r,vector<int>(c,0));
,因为vector为空的时候不能用下标赋值。
vector<vector<int>> matrixReshape(vector<vector<int>>& nums, int r, int c) {
vector<vector<int>> res(r,vector<int>(c,0));
int n = nums.size();
int m = nums[0].size();
if (m * n != r * c) return nums;
else {
int count = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
res[count/c][count%c] = nums[i][j];
count ++;
}
}
return res;
}
}
762 Prime Number of Set Bits in Binary Representation
思路:函数isPrime()判断是否是素数,由题意知,10^6 < 2^20,所以最多有20个1,所以判断1的个数是不是在2-20之间的素数就可以了。函数numOfOne()返回1的个数。
bool isPrime(int numOne) {
if (numOne ==2 || numOne == 3 || numOne == 5 || numOne == 7 || numOne == 11 ||
numOne == 13 || numOne == 17 || numOne == 19) {
return true;
}
}
int numOfOne(int num) {
int count;
for (count = 0;num;count++) {
num &= (num-1);
}
return count;
}
int countPrimeSetBits(int L, int R) {
int count = 0;
for (int i = L; i <= R; i++) {
int numOne = numOfOne(i);
if (isPrime(numOne)) count++;
}
return count;
}
496 Next Greater Element I
思路:用map记录每一个数字后的第一个大于他的数。
vector<int> nextGreaterElement(vector<int>& findNums, vector<int>& nums) {
unordered_map<int,int> map;
vector<int> res;
int size = nums.size();
int size1 = findNums.size();
for (int i = 0; i < size; i++) {
map[nums[i]] = -1;
for (int j = i + 1; j < size; j++) {
if (nums[j] > nums[i]) {
map[nums[i]] = nums[j];
break;
}
}
}
for (int num : findNums) {
res.push_back(map[num]);
}
return res;
}
摘自discuss。
vector<int> nextGreaterElement(vector<int>& findNums, vector<int>& nums) {
stack<int> s;
unordered_map<int, int> m;
for (int n : nums) {
while (s.size() && s.top() < n) {
m[s.top()] = n;
s.pop();
}
s.push(n);
}
vector<int> ans;
for (int n : findNums) ans.push_back(m.count(n) ? m[n] : -1);
return ans;
}
637 Average of Levels in Binary Tree
思路:很显然这个需要遍历,那么就是选择BFS和DFS。
vector<double> averageOfLevels(TreeNode* root) {
vector<double> res;
queue<TreeNode*> q;
q.push(root);
int n = q.size();
while (n > 0) {
double sum = 0;
for (int i = 0; i < n; i++) {
TreeNode* temp = q.front();
sum += temp->val;
q.pop();
if (temp->left) q.push(temp->left);
if (temp->right) q.push(temp->right);
}
res.push_back(double(sum/n));
n = q.size();
}
return res;
}
discuss中vote比较高的一份代码,同样是BFS。
vector<double> averageOfLevels(TreeNode* root) {
vector<double> res;
queue<TreeNode*> q;
q.push(root);
while(!q.empty()) {
long temp=0;
int s=q.size();
for(int i=0;i<s;i++) {
TreeNode* t=q.front();
q.pop();
if(t->left) q.push(t->left);
if(t->right) q.push(t->right);
temp+=t->val;
}
res.push_back((double)temp/s);
}
return res;
}
766 Toeplitz Matrix
思路1:从matrix[1][1]开始,遍历每个元素,对角线关系为[i-1][j-1],只要不相等,就直接返回false。
bool isToeplitzMatrix(vector<vector<int>>& matrix) {
int n = matrix.size();
int m = matrix[0].size();
for (int i = 1; i < n; i++) {
for (int j = 1; j < m; j++) {
if (matrix[i][j] != matrix[i-1][j-1]) return false;
}
}
return true;
}
思路2:同一个斜线上元素有一个共同点,就是列数c - 行数r是相同的,也就是说,如果数字a和b,他俩的c-r相同,那么他们就一定在同一条斜线上。
bool isToeplitzMatrix(vector<vector<int>>& matrix) {
unordered_map<int,int> map;
int n = matrix.size();
int m = matrix[0].size();
for (int r = 0; r < n; r++) {
for (int c = 0; c < m; c++) {
if (!map.count(c-r)) {
map[c-r] = matrix[r][c];
}
else {
if (map[c-r] != matrix[r][c]) return false;
}
}
}
return true;
}
693 Binary Number with Alternating Bits
思路:n % 2 得到的就是最后一位,n / 2相当于右移一位,所以每次判断最后一位和倒数第二位是否相同。
bool hasAlternatingBits(int n) {
int cur = n % 2;
n /= 2;
while (n) {
if (cur == n % 2) return false;
cur = n % 2;
n /= 2;
}
return true;
}
292 Nim Game
思路:如果是4的倍数,那么第一个选数的人,就一定会输,因为不管第一个人选的什么数a,第二个人都可以选一个数b,让a+b = 4。但是不是4的倍数的情况下,第一个人可以选一个n % 4得到的那个数,让第二个人当做在4的倍数情况下,选择第一个数,那么他就可以每次都保证剩下的数都是4的倍数。
bool canWinNim(int n) {
if (n % 4 == 0) return false;
return true;
}
136 Single Number
思路:用异或。a ^ 0 = a,a ^ a = 0,a^b^a = a^a^b = b.
int singleNumber(vector<int>& nums) {
int ans = 0;
for (int i = 0; i < nums.size(); i++) {
ans ^= nums[i];
}
return ans;
}
104 Maximum Depth of Binary Tree
思路:BFS
int maxDepth(TreeNode* root) {
int depth = 0;
queue<TreeNode*> q;
if (root == NULL) return 0;//一定要写这一句
q.push(root);
while (!q.empty()) {
int n = q.size();
for (int i = 0; i < n; i++) {
TreeNode* temp = q.front();
q.pop();
if (temp->left) q.push(temp->left);
if (temp->right) q.push(temp->right);
}
depth++;
}
return depth;
}
485 Max Consecutive Ones
思路1
int findMaxConsecutiveOnes(vector<int>& nums) {
int sum = 0;
int max = 0;
for (int num : nums) {
if (num == 1) {
sum++;
if (max < sum) max = sum;
}
else sum = 0;
}
return max;
}
但是在确定最大值还可以更简练一些
int findMaxConsecutiveOnes(vector<int>& nums) {
int sum = 0;
int max_cnt = 0;
for (int num : nums) {
if (num == 1) {
max_cnt = max(++sum,max_cnt);
}
else sum = 0;
}
return max_cnt;
}
226 Invert Binary Tree
思路1:很简单的递归。
TreeNode* invertTree(TreeNode* root) {
if (root) {
swap(root->left,root->right);
invertTree(root->left);
invertTree(root->right);
}
return root;
}
思路2:非递归
TreeNode* invertTree(TreeNode* root) {
if (root == NULL) return NULL;
queue<TreeNode*> q;
q.push(root);
while (!q.empty()) {
TreeNode* t = q.front();
q.pop();
if (t) { //一定要注意这里
q.push(t->left);
q.push(t->right);
swap(t->left,t->right);
}
}
return root;
}
520 Detect Capital
思路:判断大写字母个数,全部都是大写字母,首字母是大写,一个大写没有。
bool detectCapitalUse(string word) {
int cnt = 0;
for (char c : word) {
if ('Z' - c >= 0)
cnt++;
}
return (cnt == 0) || (cnt == word.size()) || (cnt == 1 && 'Z' - word[0] >= 0);
}
690 Employee Importance
思路:DFS
int getImportance(vector<Employee*> employees, int id) {
unordered_map<int,Employee*> map;
for (auto element : employees) {
map[element->id] = element;
}
return help(map,id);
}
int help(unordered_map<int,Employee*> & map,int id) {
int sum = map[id]->importance;
for (auto element : map[id]->subordinates) {
sum += help(map,element);
}
return sum;
}
258 Add Digits
数学归纳法:input:0,1,2,3,4,。。。。
output:0,1,2,3,4,5,6,7,8,9,1,2,3,4.。。
int addDigits(int num) {
return 1 + (num - 1) % 9;
}
283 Move Zeroes
思路:把0和后面的数字调换
void moveZeroes(vector<int>& nums) {
int zeroLoc = 0;
for (int i = 0; i < nums.size(); i++) {
if (nums[i]) {
swap(nums[i],nums[zeroLoc]);
zeroLoc++;
}
}
}