LeetCode20——有效的括号
题目:
给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
注意空字符串可被认为是有效字符串。
示例 1:
输入: "()"
输出: true
示例 2:
输入: "()[]{}"
输出: true
示例 3:
输入: "(]"
输出: false
示例 4:
输入: "([)]"
输出: false
示例 5:
输入: "{[]}"
输出: true
思路:
用栈的存储括号,左右同种类型的括号相匹配才可以顺利出栈,注意判断栈的容量为空,以及首字符为 右括号的情况。
代码:
class Solution {
public:
bool isValid(string s) {
stack<char>t;
for (int i = 0; i < s.length(); i++)
{
if (s[i] == '(' || s[i] == '[' || s[i] == '{')
t.push(s[i]);
else if (s[i] == ')')
{
if (i == 0 || t.size() == 0 || t.top() != '(')
return false;
else
t.pop();
}
else if (s[i] == ']')
{
if (i == 0 || t.size() == 0 || t.top() != '[')
return false;
else
t.pop();
}
else if(s[i]=='}')
{
if (i == 0 || t.size() == 0 || t.top() != '{')
return false;
else
t.pop();
}
}
return t.empty();
}
};
LeetCode150——逆波兰表达式
题目:
根据逆波兰表示法,求表达式的值。
有效的运算符包括 +, -, *, / 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。
说明:
整数除法只保留整数部分。
给定逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。
示例 1:
输入: ["2", "1", "+", "3", "*"]
输出: 9
解释: ((2 + 1) * 3) = 9
示例 2:
输入: ["4", "13", "5", "/", "+"]
输出: 6
解释: (4 + (13 / 5)) = 6
示例 3:
输入: ["10", "6", "9", "3", "+", "-11", "*", "/", "*", "17", "+", "5", "+"]
输出: 22
解释:
((10 * (6 / ((9 + 3) * -11))) + 17) + 5
= ((10 * (6 / (12 * -11))) + 17) + 5
= ((10 * (6 / -132)) + 17) + 5
= ((10 * 0) + 17) + 5
= (0 + 17) + 5
= 17 + 5
= 22
思路:
读入数字的时候放入栈中,遇到运算符号就取出栈顶的前两个元素进行运算。两个非常好用的函数 string转int -> stoi(s,0,10),以及int转整型 to_string。
代码:
class Solution {
public:
int evalRPN(vector<string>& tokens) {
int len = tokens.size();
if (len == 0) return 0;
stack<string>st;
for (int i = 0; i < len; i++)
{
if (tokens[i] != "+" &&tokens[i] != "-"&&tokens[i] != "/"&& tokens[i] != "*")
{
st.push(tokens[i]);
}
else if (tokens[i] == "+")
{
string num1 = st.top();
st.pop();
string num2 = st.top();
st.pop();//string 字符串转数字,stoi(s,p,b) 把字符串s从p开始转换成b进制的int
int n1 = stoi(num1, 0, 10);
int n2 = stoi(num2, 0, 10);
int result = n2 + n1;
string res = to_string(result);
st.push(res);
}
else if (tokens[i] == "-")
{
string num1 = st.top();
st.pop();
string num2 = st.top();
st.pop();//string 字符串转数字,stoi(s,p,b) 把字符串s从p开始转换成b进制的int
int n1 = stoi(num1, 0, 10);
int n2 = stoi(num2, 0, 10);
int result = n2 - n1;
string res = to_string(result);
st.push(res);
}
else if (tokens[i] == "*")
{
string num1 = st.top();
st.pop();
string num2 = st.top();
st.pop();//string 字符串转数字,stoi(s,p,b) 把字符串s从p开始转换成b进制的int
int n1 = stoi(num1, 0, 10);
int n2 = stoi(num2, 0, 10);
int result = n2 * n1;
string res = to_string(result);
st.push(res);
}
else
{
string num1 = st.top();
st.pop();
string num2 = st.top();
st.pop();//string 字符串转数字,stoi(s,p,b) 把字符串s从p开始转换成b进制的int
int n1 = stoi(num1, 0, 10);
int n2 = stoi(num2, 0, 10);
int result = n2/n1;
string res = to_string(result);
st.push(res);
}
}
return stoi(st.top());
}
};
LeetCode145——二叉树先序遍历的非递归实现:https://www.cnblogs.com/kangna/p/11846156.html
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
stack<TreeNode*>st;
vector<int>ans;
if (root == nullptr)
return ans;
st.push(root);
while (!st.empty())
{
TreeNode* temp = st.top();
st.pop();
ans.push_back(temp->val);
if (temp->right != nullptr)
st.push(temp->right);
if (temp->left != nullptr)
st.push(temp->left);
}
return ans;
}
};
LeetCode146——二叉树中序遍历的非递归实现:https://www.cnblogs.com/kangna/p/11846156.html
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
stack<TreeNode*>st;
vector<int>ans;
if (root == nullptr)
return ans;
TreeNode* p = root;
while (!st.empty()||p)//注意这个条件“||”
{
if (p)
{
st.push(p);
p = p->left;
}
else
{
TreeNode* temp = st.top();
ans.push_back(temp->val);
st.pop();
p = temp->right;
}
}
return ans;
}
};
LeetCode147——二叉树的层序遍历:
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>>result;
if (root == NULL)
return result;
vector<int>temp;
queue<TreeNode*>record;
record.push(root);
while (record.size()!=0)
{
int size = record.size();
while (size--)
{
TreeNode* tmp = record.front();
record.pop();
temp.push_back(tmp->val);
if (tmp->left != NULL)
record.push(tmp->left);
if (tmp->right != NULL)
record.push(tmp->right);
}
result.push_back(temp);
temp.clear();
}
return result;
}
};
LeetCode107——二叉树的层次遍历II
给定一个二叉树,返回其节点值自底向上的层次遍历。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)
例如:
给定二叉树 [3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
返回其自底向上的层次遍历为:
[
[15,7],
[9,20],
[3]
]
思路:
其实就是把层序遍历的每层结果先放到栈里面,然后出栈在放入容器中,调换了一下输出顺序而已。
代码:
class Solution {
public:
vector<vector<int>> levelOrderBottom(TreeNode* root) {
vector<vector<int>>ans;
if (root == nullptr)
return ans;
queue<TreeNode*>q;
stack<vector<int>>st;
vector<int>layer;
TreeNode* pNode = root;
q.push(pNode);
while (!q.empty())
{
int size = q.size();
while (size--)
{
TreeNode* p = q.front();
q.pop();
layer.push_back(p->val);
if (p->left)
q.push(p->left);
if (p->right)
q.push(p->right);
}
st.push(layer);
layer.clear();
}
while (!st.empty())
{
ans.push_back(st.top());
st.pop();
}
return ans;
}
};
LeetCode103——二叉树的锯齿形层次遍历
给定一个二叉树,返回其节点值的锯齿形层次遍历。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。
例如:
给定二叉树 [3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
返回锯齿形层次遍历如下:
[
[3],
[20,9],
[15,7]
]
思路:
其实还是正常的进行层序遍历,只不过设置了一个标志为flag,相邻两层的标志位相反,第一层正常入向量,第二层先入一个临时的栈,最后再入向量中,这样上下两层的节点顺序就相反了。
代码:
class Solution {
public:
vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
vector<vector<int>>ans;
if (root == nullptr)
return ans;
queue<TreeNode*>q;
stack<vector<int>>st;
vector<int>layer;
TreeNode* pNode = root;
q.push(pNode);
bool flag = true;
stack<int>rev;
while (!q.empty())
{
int size = q.size();
while (size--)
{
TreeNode* p = q.front();
q.pop();
if(flag==true)
layer.push_back(p->val);
else
{
rev.push(p->val);
}
if (p->left)
q.push(p->left);
if (p->right)
q.push(p->right);
}
if (flag == true)
{
flag = false;
}
else
{
while (!rev.empty())
{
int temp = rev.top();
layer.push_back(temp);
rev.pop();
}
flag = true;
}
ans.push_back(layer);
layer.clear();
}
return ans;
}
};
LeetCode199——二叉树的右视图
给定一棵二叉树,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。
示例:
输入: [1,2,3,null,5,null,4]
输出: [1, 3, 4]
解释:
1 <---
/ \
2 3 <---
\ \
5 4 <---
思路:
其实还是二叉树的层序遍历,只不过保留的是每一层节点的最后一个节点的值。
代码:
class Solution {
public:
vector<int> rightSideView(TreeNode* root) {
vector<int>ans;
if (root == NULL)
return ans;
TreeNode* pNode = root;
queue<TreeNode*>q;
q.push(pNode);
while (!q.empty())
{
int size = q.size();
while (size--)
{
TreeNode* temp = q.front();
q.pop();
if (size == 0)
ans.push_back(temp->val);
if (temp->left)
q.push(temp->left);
if (temp->right)
q.push(temp->right);
}
}
return ans;
}
};
LeetCode279——完全平方数的和
题目:
给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, ...)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。
示例 1:
输入: n = 12
输出: 3
解释: 12 = 4 + 4 + 4.
示例 2:
输入: n = 13
输出: 2
解释: 13 = 4 + 9.
思路:
其实动态规划的做法比较好想到,这里是用了图论的方法,比如从10开始有10->9,10->6,10->1,这三条路径,然后把这三个点入队列,把step+1,依次取出这些节点,然后放入他们能够到达的下一个节点,step继续加一。注意这里有很多重复计算,可以设置一个visited数组记录访问过的元素,然后跳过计算。直到出现值为0的节点,返回step就可以了。
class Solution {
public:
int numSquares(int n) {
queue<pair<int, int>>q;
q.push(make_pair(n, 0));
vector<bool>visited(n + 1, false);
visited[n] = true;
while (!q.empty())
{
int num = q.front().first;
int step = q.front().second;
q.pop();
for (int i = 1;; i++)
{
int a = num - i * i;
if (a < 0)
break;
if (a == 0)
return step + 1;
if (!visited[a])
{
q.push(make_pair(a, step + 1));
visited[a] = true;
}
}
}
throw invalid_argument("No Solution");
}
};
//动态规划的做法
class Solution {
public:
int numSquares(int n) {
vector<int>dp(n + 1);
dp[0] = 0;
for (int i = 1; i <= n; i++)
{
int min = 9999;
for (int j = 1; j <= int(sqrt(n));j++)
{
if (i-j*j >=0)
{
int temp = dp[i - j * j];
if (temp + 1 < min)
{
dp[i] = temp + 1;
min = dp[i];
}
}
}
}
return dp[n];
}
};
优先级队列的底层是“最大堆”,用法要特别注意,常用来解决topK的问题。
LeetCode347——前k个高频元素
给定一个非空的整数数组,返回其中出现频率前 k 高的元素。
示例 1:
输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]
示例 2:
输入: nums = [1], k = 1
输出: [1]
思路:
首先还是用map获得对应数字的出现频率,然后创建一个大小为k的优先级队列,底层选择最小堆实现,然后放入pair(频率,数字),每当一个新的map中的pair过来的时候(注意这个时候两个pair里面的元素位置是反过来的),比较频率的大小,如果新的频率大就加入优先级队列中,不大就不做操作,这样最后优先级队列里面的就是出现频率最多的k元素。
代码:
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
int len = nums.size();
vector<int>res;
unordered_map<int,int>mp;//元素对应的频率;
for (int i = 0; i < len; i++)
{
mp[nums[i]]++;
}
priority_queue<pair<int, int>, vector < pair<int, int>>, greater<pair<int, int>>> pq;
//降序队列
//priority_queue <int, vector<int>, greater<int> > q;
//升序队列(默认)
//priority_queue <int, vector<int>, less<int> >q;
for (unordered_map<int, int>::iterator it = mp.begin(); it != mp.end(); it++)
{
if (pq.size() == k)
{
if (it->second > pq.top().first)
{
pq.pop();
pq.push(make_pair(it->second, it->first));
}
}
else
pq.push(make_pair(it->second, it->first));
}
while (pq.size()!=0)
{
res.push_back(pq.top().second);
pq.pop();
}
return res;
}
};