LeetCode Easy排序前50道题

本文精选了LeetCode上的经典算法题目,通过实例详细解析了包括字符串处理、二叉树操作、位运算等多种类型的算法解决方案,帮助读者深入理解并掌握算法实现技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

771 Jewels and Stones

 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);
    }

669 Trim a Binary Search Tree

 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
思路:

  1. 判断新的shape个数是否匹配if (m * n != r * c) return nums;
  2. 如果匹配,说明可以转换。把数都放进一个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++;
            }
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值