理解状态转移方程就可以简单解决 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;
}
};
最朴素的方法是遍历所有节点累加,除此之外其实可以只统计最后一层:左右子树深度相等则左边为满二叉树,右边比左边底则右边一定为满二叉树
/**
* 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;
}
};
很无聊的一道题,没有意义
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;
}
};
本题思路是使用栈保存括号,左括号进栈右括号出栈。优化点在于我们可以只使用加法:减法视为负数,这样可以避免字符串逆序重排
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;
}
};
栈的先进后出用队列实现有两种思路:采用辅助队列,或者每次入栈时将前面的全部取出放在后面
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;
};
本题可以用递归解决,类似于深度优先,也可以用迭代解决,类似于广度优先
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;
}
};
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;
}
};