保研机试练习:leetcode算法top200(第二弹)

🌮101.对称二叉树(简单)

🍟题目描述

🍟题目反思

对称二叉树,对每个节点来说,就是当前节点相同,且左右镜像相等。这道题目重点也是在于掌握递归检查树上。

🍟代码

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    bool check(TreeNode *p, TreeNode *q) {
        if (p==nullptr && q==nullptr) return true;
        if (p==nullptr || q==nullptr) return false;
        return p->val == q->val && check(p->left, q->right) && check(p->right, q->left);//要求根相等且左右对称相等
    }
​
    bool isSymmetric(TreeNode* root) {
        return check(root, root);
    }
};

🌮104.二叉树的最大深度(简单)

🍟题目描述

🍟题目反思

这道题目也是使用递归的方法,主要是巩固一下递归的方法。

🍟代码

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    int maxDepth(TreeNode* root) {
        if(root==nullptr) return 0;
        return max(maxDepth(root->left),maxDepth(root->right))+1;
    }
};

🌮108.将有序数组转换为二叉搜索树(简单)

🍟题目描述

🍟题目反思

这道题目也是使用递归的方法,但是有一定的思路在里边,建议顺一遍过程。

🍟代码

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* sortedArrayToBST(vector<int>& nums) {
        return helper(nums, 0, nums.size() - 1);
    }//每次都选出根节点,左右两组分别递归一下
​
    TreeNode* helper(vector<int>& nums, int left, int right) {
        if (left > right) {
            return nullptr;
        }
​
        // 总是选择中间位置左边的数字作为根节点
        int mid = (left + right) / 2;
​
        TreeNode* root = new TreeNode(nums[mid]);
        root->left = helper(nums, left, mid - 1);
        root->right = helper(nums, mid + 1, right);
        return root;
    }
};

🌮112.路径总和(简单)

🍟题目描述

🍟题目反思

这道题目也是用的递归方法,建议顺一遍思路。

🍟代码

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    bool hasPathSum(TreeNode *root, int sum) {
        if (root == nullptr) {
            return false;
        }
        if (root->left == nullptr && root->right == nullptr) {
            return sum == root->val;
        }
        return hasPathSum(root->left, sum - root->val) ||
               hasPathSum(root->right, sum - root->val);
    }
};

🌮125.验证回文串(简单)

🍟题目描述

🍟题目反思

这道题目掌握几个函数:

  • isalnum(char):用于判断当前字符是否是字母或数字,如果是,返回true,不是返回false;
  • tolower(char):用于将大小写字母转换成小写字母,toupper(char)用于转换成大写字母;
  • reverse(s.begin(),s.end()):用于将字符串反转

🍟代码

class Solution {
public:
    bool isPalindrome(string s) {
        string ans;
        for (char ch: s) {
            if (isalnum(ch)) {
                ans += tolower(ch);
            }
        }
        string ss=ans;
        reverse(ss.begin(),ss.end());
        return ss==ans;
    }
};

🌮130.被围绕的区域(中等)

🍟题目描述

🍟题目反思

这道题目的思路是:

所有的不被包围的 O 都直接或间接与边界上的 O 相连。我们可以利用这个性质判断 O 是否在边界上,具体地说:

    对于每一个边界上的 O,我们以它为起点,标记所有与它直接或间接相连的字母 O;
    最后我们遍历这个矩阵,对于每一个字母:

  • 如果该字母被标记过,则该字母为没有被字母 X 包围的字母 O,我们将其还原为字母 O;
  • 如果该字母没有被标记过,则该字母为被字母 X 包围的字母 O,我们将其修改为字母 X。

利用了队列queue,和BFS的操作流程,每次将不能被变成X的O加入队列,然后依次判断其四周是否有同样不能被变成X的O。

🍟代码

class Solution {
public:
    const int dx[4] = {1, -1, 0, 0};
    const int dy[4] = {0, 0, 1, -1};
​
    void solve(vector<vector<char>>& board) {
        int n = board.size();//行数
        if (n == 0) {
            return;
        }
        int m = board[0].size();//列数
        queue<pair<int, int>> que;//队列,把所有的O放入
        //把四条最外边的行列的O记录下,这些都不能被去掉
        for (int i = 0; i < n; i++) {
            if (board[i][0] == 'O') {
                que.emplace(i, 0);//相当于que.push_back({i,0});存入的是x、y位置
                board[i][0] = 'A';
            }
            if (board[i][m - 1] == 'O') {
                que.emplace(i, m - 1);
                board[i][m - 1] = 'A';
            }
        }
        for (int i = 1; i < m - 1; i++) {
            if (board[0][i] == 'O') {
                que.emplace(0, i);
                board[0][i] = 'A';
            }
            if (board[n - 1][i] == 'O') {
                que.emplace(n - 1, i);
                board[n - 1][i] = 'A';
            }
        }
        //剩下的都有上下左右格子了
        while (!que.empty()) {
            int x = que.front().first, y = que.front().second;
            que.pop();
            for (int i = 0; i < 4; i++) {
                int mx = x + dx[i], my = y + dy[i];
                if (mx < 0 || my < 0 || mx >= n || my >= m || board[mx][my] != 'O') {
                    continue;
                }
                que.emplace(mx, my);//这里是O,且不能被去掉
                board[mx][my] = 'A';
            }
        }
        for (int i = 0; i < n; i++) {//遍历整个矩阵
            for (int j = 0; j < m; j++) {
                if (board[i][j] == 'A') {//这些都是不能被去掉的O
                    board[i][j] = 'O';
                } else if (board[i][j] == 'O') {//这些是能被去掉的O
                    board[i][j] = 'X';
                }
            }
        }
    }
};

🌮160.相交链表——双指针法(简单)

🍟题目描述

🍟题目反思

这道题目使用双指针的方法:

只有当链表 headA 和 headB 都不为空时,两个链表才可能相交。因此首先判断链表 headA 和 headB 是否为空,如果其中至少有一个链表为空,则两个链表一定不相交,返回 null。

当链表 headA 和 headB 都不为空时,创建两个指针 pA 和 pB,初始时分别指向两个链表的头节点 headA 和 headB,然后将两个指针依次遍历两个链表的每个节点。具体做法如下:

  • 每步操作需要同时更新指针 pA 和 pB。
  • 如果指针 pA 不为空,则将指针 pA 移到下一个节点;如果指针 pB 不为空,则将指针 pB 移到下一个节点。
  • 如果指针 pA 为空,则将指针 pA 移到链表 headB 的头节点;如果指针 pB 为空,则将指针 pB 移到链表 headA 的头节点。
  • 当指针 pA 和 pB 指向同一个节点或者都为空时,返回它们指向的节点或者 null。

🍟代码

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        if (headA == nullptr || headB == nullptr) {
            return nullptr;
        }
        ListNode *pA = headA, *pB = headB;
        while (pA != pB) {
            pA = pA == nullptr ? headB : pA->next;//到头就转到另一条链表,否则就往后移
            pB = pB == nullptr ? headA : pB->next;
        }
        return pA;//如果二者相等就会返回相交节点,否则二者同到null就会返回null
    }
};

🌮168.Excel表列名称(简单)

🍟题目描述

🍟题目反思

理解清楚后就会发现,这道题目就是另类的进制转换,字母转数字的基数是26,类似十进制转二进制,每次对26取余。这里需要注意的一点是,A是1,所以每次要得到正确结果需要先减1.

🍟代码

class Solution {
public:
    string convertToTitle(int columnNumber) {
        string ans;
        int cur;
        while(columnNumber>0) {
            cur=(columnNumber-1)%26;
            ans+=cur+'A';
            columnNumber=(columnNumber-cur)/26;
        }
        reverse(ans.begin(),ans.end());
        return ans;
    }
};

🌮171.Excel表列序号(简单)

🍟题目描述

同理,上道题目翻过来

🍟题目反思

类似二进制转十进制

🍟代码

class Solution {
public:
    int titleToNumber(string columnTitle) {
        int len=columnTitle.size();
        if(len==1) return columnTitle[0]-'A'+1;
        long long ans=0;
        for(int i=0;i<len-1;i++)
        {
            ans+=(columnTitle[i]-'A'+1);
            ans*=26;
            //cout<<columnTitle[i]-'A'+1<<" "<<ans<<endl;//
        }
        ans+=(columnTitle[len-1]-'A'+1);
        //cout<<columnTitle[len-1]-'A'+1<<" "<<ans<<endl;//
        return ans;
    }
};

🌮190.颠倒二进制位(简单)

🍟题目描述

🍟题目反思

这道题目是二进制位的处理,主要是学会左移、右移等操作。

🍟代码

class Solution {
public:
    uint32_t reverseBits(uint32_t n) {
        int i=32;
        uint32_t ans=0;
        while(i>0){
            ans<<=1;//左移一位,为当前处理位留出位置
            ans+=n&1;//取出最低位,并加入结果
            n>>=1;//n丢弃掉已经处理过的最低位
            i--;
        }
        return ans;
    }
};

🌮191.位1的个数(简单)

🍟题目描述

🍟题目反思

这道题目就是模拟十进制转二进制然后计算其中1的个数,注意记得反转。

🍟代码

class Solution {
public:
    int hammingWeight(int n) {
        string s;
        while(n>0) 
        {
            s+=n%2+'0';
            n/=2;
        }
        reverse(s.begin(),s.end());
        int ans=0;
        for(int i=0;i<s.size();i++) 
        {
            if(s[i]=='1') ans++;
        }
        return ans;
    }
};

⭐创作不易,点个赞吧~

⭐点赞收藏不迷路~

  • 18
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值