leetcode解题思路分析(三十一)221—227题

  1. 最大正方形
    在一个由 0 和 1 组成的二维矩阵内,找到只包含 1 的最大正方形,并返回其面积。

理解状态转移方程就可以简单解决 dp(i, j) = min(dp(i − 1, j), dp(i − 1, j − 1), dp(i, j − 1)) + 1

class Solution {
public:
    int maximalSquare(vector<vector<char>>& matrix) {
        if (matrix.size() == 0 || matrix[0].size() == 0) {
            return 0;
        }
        int maxSide = 0;
        int rows = matrix.size(), columns = matrix[0].size();
        vector<vector<int>> dp(rows, vector<int>(columns));
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < columns; j++) {
                if (matrix[i][j] == '1') {
                    if (i == 0 || j == 0) {
                        dp[i][j] = 1;
                    } else {
                        dp[i][j] = min(min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]) + 1;
                    }
                    maxSide = max(maxSide, dp[i][j]);
                }
            }
        }
        int maxSquare = maxSide * maxSide;
        return maxSquare;
    }
};

  1. 完全二叉树
    给出一个完全二叉树,求出该树的节点个数。

最朴素的方法是遍历所有节点累加,除此之外其实可以只统计最后一层:左右子树深度相等则左边为满二叉树,右边比左边底则右边一定为满二叉树

/**
 * 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:
    int countNodes(TreeNode* root) {
        int cnt = 0;
        queue<TreeNode *> nodes;
        if (root == NULL)
            return cnt;
        nodes.push(root);
        while (nodes.size())
        {
            TreeNode *curr = nodes.front();
            nodes.pop();
            cnt++;
            if (curr->left)
                nodes.push(curr->left);
            if (curr->right)
                nodes.push(curr->right);
        }
        return cnt;
    }
};
/**
 * 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:
    int countNodes(TreeNode* root) {
        if(!root)
            return 0;
        int left = depth(root->left);
        int right = depth(root->right);
        if(left==right){
            return pow(2,left)+countNodes(root->right);
        }
        else{
            return  pow(2,right)+countNodes(root->left);
        }
    }

    int depth(TreeNode* root){
        int ans = 0;
        while(root){
            ans++;
            root = root->left;
        }
        return ans;
    }
};

  1. 矩形面积
    在二维平面上计算出两个由直线构成的矩形重叠后形成的总面积。

很无聊的一道题,没有意义

class Solution {
public:
    int computeArea(int A, int B, int C, int D, int E, int F, int G, int H) {
        //先判定不重叠的情况,不重叠的话,就是两者面积相加
        if((C <= E || G <= A || D <= F || H <= B)){
            return (C - A) * (D - B) + (G - E) * (H - F);
        };
        //用向量的思想来算:
        //计算一共分四种情况:[A,E,C,G], [E,A,G,C], [A,E,G,C], [E,A,C,G]。
        //所以,可以得到的是:dx = 两边长 - 最大的长;
        //算两条边的边长
        int whole_x = (C - A) + (G - E);
        int whole_y = (D - B) + (H - F);

        //算最大的长
        int x[4] = {A,C,E,G};
        int y[4] = {B,D,F,H};
        //排序选最大和最小值
        sort(x,x+4);
        sort(y,y+4);
        //最长边
        int large_x = x[3] - x[0];
        int large_y = y[3] - y[0];
        //重叠区域面积
        int delta_area = (whole_x - large_x) * (whole_y - large_y);
        //两个矩形面积
        int area_a = (C - A) * (D - B);
        int area_b = (G - E) * (H - F);

        //这里容易越界
        return area_b - delta_area + area_a;

    }
};


  1. 基本计算器
    实现一个基本的计算器来计算一个简单的字符串表达式的值。
    字符串表达式可以包含左括号 ( ,右括号 ),加号 + ,减号 -,非负整数和空格 。

本题思路是使用栈保存括号,左括号进栈右括号出栈。优化点在于我们可以只使用加法:减法视为负数,这样可以避免字符串逆序重排

class Solution {
public:
    int calculate(string s) {
        stack<int> st;
        int res = 0, n = s.size(), sign = 1;
        for(int i=0; i<n; i++) {
            int num = 0;
            if(s[i] >= '0') {
                while(i<n && s[i] >= '0') {
                    num = num * 10 + (s[i] - '0');
                    i++;
                }
                i--;
                res += sign * num;
            }
            else if(s[i] == '+') sign = 1;
            else if(s[i] == '-') sign = -1;
            else if(s[i] == '(') {
                st.push(res);
                st.push(sign);
                res = 0;
                sign = 1;
            }
            else if(s[i] == ')') {
                res *= st.top(); st.pop();
                res += st.top(); st.pop();
            }
        }
        return res;
    }
};


  1. 用队列实现栈

栈的先进后出用队列实现有两种思路:采用辅助队列,或者每次入栈时将前面的全部取出放在后面

class MyStack {
public:
    /** Initialize your data structure here. */
    MyStack() = default;
    
    /** Push element x onto stack. */
    void push(int x) {
        que.push(x);
        for (int i = 0; i + 1 < que.size(); i++) {
            que.push(que.front());
            que.pop();
        }
    }
    
    /** Removes the element on top of the stack and returns that element. */
    int pop() {
        int val = top();
        que.pop();
        return val;
    }
    
    /** Get the top element. */
    int top() {
        return que.front();
    }
    
    /** Returns whether the stack is empty. */
    bool empty() {
        return que.empty();
    }

private:
    queue<int> que;
};


  1. 翻转二叉树
    翻转一棵二叉树。

本题可以用递归解决,类似于深度优先,也可以用迭代解决,类似于广度优先

class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        if(!root) return nullptr;
        swap(root->left, root->right);      
        root->left = invertTree(root->left);
        root->right = invertTree(root->right);
        return root;
    }
};

class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        stack<TreeNode*> stk;
        if(root) stk.push(root);
        while(stk.size()) {
            TreeNode* tr = stk.top();
            stk.pop();
            swap(tr->left, tr->right);
            if(tr->left) stk.push(tr->left);
            if(tr->right) stk.push(tr->right);
        }
        return root;
    }
};

  1. 基本计算器2
    实现一个基本的计算器来计算一个简单的字符串表达式的值。
    字符串表达式仅包含非负整数,+, - ,*,/ 四种运算符和空格 。 整数除法仅保留整数部分。
class Solution {
public:
    int calculate(string s) {
        int begin = 0;
       return calHelper(s, begin);

    }
    int calHelper(string s, int& i) //i用于记录计算开始的索引
    {
        char operation = '+';
        stack<int> nums;
        int num = 0;
        int res = 0;
        bool flag = false;
        for (i; i < s.size(); i++)
        {
            if (s[i] >= '0' && s[i] <= '9')
            {
                num = num * 10 + (s[i] - '0');
            }
             if (s[i] == '(')
            {
                num = calHelper(s, ++ i); //从i的下一个开始计算, 进入递归
                i++; //计算完之后的i指向)所以再++
            }
            if (((s[i] < '0' || s[i] > '9') && s[i] != ' ') || i >= s.size() - 1) // 继续计算
            {
                int pre = 0;
                switch (operation)
                {
                case '+': nums.push(num);
                    break;
                case '-': nums.push(-num);
                    break;
                case '*':
                    pre = nums.top();
                    nums.pop();
                    nums.push(pre * num);
                    break;
                case '/':
                    pre = nums.top();
                    nums.pop();
                    nums.push(pre / num);
                    break;
                }

                operation = s[i];
                num = 0;
            }
            if (s[i] == ')') //遇到)回到上一级递归
            {
                break;
            }
        }
        while (!nums.empty())
        {
            res += nums.top();
            nums.pop();
        }
        return res;
    }
};

你可能感兴趣的:(面试)