今天刷的内容全都是leetcode中栈和队列的使用
leetcode20:判断是否是匹配括号等;
class Solution { public: bool isValid(string s) { int size=s.length(); if(size%2!=0){ return false; } stack<char> Stack;//构建一个stack int i; for(i=0;i<size;i++){ if(s[i]=='('||s[i]=='{'||s[i]=='['){ Stack.push(s[i]); } else{ if(Stack.empty()) return false; if((Stack.top()=='('&&s[i]==')')||(Stack.top()=='{'&&s[i]=='}')||(Stack.top()=='['&&s[i]==']')) Stack.pop(); } } if(Stack.empty()){ return true; } else return false; } };
构建一个栈数据结构来存储相应的数据,如果是左括号就入栈,如果是右括号就出栈,直到所有元素都遍历,如果栈不为空则返回false;
leetcode150:波特兰后续表达式计算,学习的内容是atoi()函数的使用;,时间复杂度都是O(n);
class Solution { public: int evalRPN(vector<string>& tokens) { int size=tokens.size(); if(size==1){ return atoi(tokens[0].c_str()); } stack<int> ss; int i=0; for(i;i<size;i++){ if(tokens[i] != "+" && tokens[i] != "-" && tokens[i] != "*" && tokens[i] != "/"){ //首先将字符串转换为C字符串,然后转换为int类型的数据 ss.push(atoi(tokens[i].c_str())); } else{ int m=ss.top(); ss.pop(); int n=ss.top(); ss.pop(); if(tokens[i]=="+") ss.push(m+n); if(tokens[i]=="-") ss.push(n-m); if(tokens[i]=="*") ss.push(m*n); if(tokens[i]=="/") ss.push(n/m); } } return ss.top(); };
leetcode71:简化一个字符串linux文件路径的字符串:
class Solution { public: string simplifyPath(string path) { //简化路径名称 使用一个栈来维护字符串 int size=path.size(); int i=0; if(path=="") return ""; stack<string> stacks; //首先遍历所有的字符串中的字符 for(i=0;i<size;){ while(i<size&&path[i]=='/'){ i++; } string s=""; while(i<size&&path[i]!='/'){ s+=path[i++]; } if(s==".."&&!stacks.empty()){ stacks.pop();// 如果是..弹出相应的元素 } else{ if(s!=".."&&s!="."&&s!=""){ stacks.push(s); } } } if(stacks.empty()){ return "/";//如果当前的栈为空 返回当前路径 } string ans=""; while(!stacks.empty()) { ans="/"+stacks.top()+ans; stacks.pop(); } return ans; } };
算法的和时间复杂度为O(n);
栈和递归的紧密联系:与二叉树的使用;
leetcode144; 先序遍历算法的使用
1:递归算法的简单实现:
class Solution { public: vector<int> ans;//增加一个类变量来维护相应的数据 public: if(root){ ans.push_back(root->val); preorderTraversal(root->left); preorderTraversal(root->right); } return ans; } };
居然能通过 运算时间是4ms
2.自己模拟一个栈了维护相应的数据;
struct command{ string flag; TreeNode* node; command(string ss,TreeNode *Node):flag(ss),node(Node){} };//主机构建一个结构体来存储相应的Node节点还有一个flag标志 class Solution { public: vector<int> ans; public: vector<int> preorderTraversal(TreeNode* root) { //使用栈来模拟递归算法的使用; if(root==NULL){ return ans; } stack<command> result; result.push(command("go",root));//首先将根节点入栈中 while(!result.empty()){ command top=result.top(); result.pop(); if(top.flag=="out"){ ans.push_back((top.node)->val); } else{//对于每一次节点都要进行相应的入栈 if(top.node->right!=NULL){ result.push(command("go",top.node->right)); } if(top.node->left!=NULL){ result.push(command("go",top.node->left)); } result.push(command("out",top.node)); } } return ans; } };
以上的运行时间为3ms
3:采用书本中的构建栈的方式较为复杂:
vector<int> preorderTraversal(TreeNode* root) { vector<int> ans; TreeNode *p=root; if(root==NULL){ return ans; } stack<TreeNode *> ss; while(p!=NULL||!ss.empty()){ while(p!=NULL){ ans.push_back(p->val); ss.push(p); p=p->left; }//首先遍历左行节点到最根部,然后再push进右节点; if(!ss.empty()){ TreeNode *q=ss.top(); ss.pop(); p=q->right; } } return ans; }
同理相应的中序遍历的方式也是一样的:
leetcode94:
递归实现:
class Solution {//中序遍历算法 public: vector<int> ans;//同样设置一个类属性来存储相应的返回值 vector<int> inorderTraversal(TreeNode* root) { if(root){ inorderTraversal(root->left); ans.push_back(root->val); inorderTraversal(root->right); } return ans; } };
2.模拟栈来实现递归
struct command{ string val; TreeNode *Node; command(string val,TreeNode *node):val(val),Node(node){} }; class Solution {//中序遍历算法 public: vector<int> ans; vector<int> inorderTraversal(TreeNode* root) { // //递归调用 但是返回值的问题需要解决 返回的是vector<int> 类型的数据 // /* // vector<int> ans; // if(root==NULL){ // return ans.push_back(NULL); // } // else{ // ans.push_back(root->val); // ans.push_back(inorderTraversal(root->left)); // ans.push_back(inorderTranvesal(root->right)); // } // */ // vector<int> ans; // TreeNode *p=root; // if(p==NULL){ // return ans;// // } // stack<TreeNode *> stackss; // while(p!=NULL||!stackss.empty()){ // while(p!=NULL){ // stackss.push(p); // p=p->left;//首先找到最左边的子节点; // } // if(!stackss.empty()){ // TreeNode *q=stackss.top(); // ans.push_back(q->val); // stackss.pop(); // p=q->right; // } // } // return ans; // if(root){ // inorderTraversal(root->left); // ans.push_back(root->val); // inorderTraversal(root->right); // } // return ans; if(root==NULL){ return ans; } stack<command> ss; ss.push(command("go",root)); while(!ss.empty()){ command top=ss.top(); ss.pop(); if(top.val=="cout"){ ans.push_back(top.Node->val); } else{ if(top.Node->right!=NULL){ ss.push(command("go",top.Node->right));} ss.push(command("cout",top.Node)); if(top.Node->left!=NULL){ ss.push(command("go",top.Node->left));} } } return ans; } };
同理后续遍历采用新的方式也是可以实现:这里不再做详细的介绍了;
队列的内容;
主要是关于树的层序遍历和无权图的最短路径;
leetcode102:
关于树的层序遍历方式;
class Solution { public: vector<vector<int>> levelOrder(TreeNode* root) { //使用队列的数据结构来存储相应的结点,每当有节点pop出去就向队尾中添加结点 //C++中队列的数据结构是Queue vector<vector<int>> ans; if(root==NULL){ return ans; } queue<TreeNode *> result;//首先将相应的root元素入队 result.push(root); while(!result.empty()){ //构建一个行的队列,用来存储相应的队列中临时数据 vector<int> tempVector; queue<TreeNode *> tempQueue; while(!result.empty()){ TreeNode *front=result.front(); result.pop(); tempVector.push_back(front->val); if(front->left!=NULL){ tempQueue.push(front->left); } if(front->right!=NULL){ tempQueue.push(front->right); } } ans.push_back(tempVector); result=tempQueue; } return ans; } };
leetcode103:层序遍历树,当时树的遍历方式是zip zap的方式Z的方式来遍历树
class Solution { public: vector<vector<int>> zigzagLevelOrder(TreeNode* root) { //方法相同还是使用队列的数据结构来进行存储相应的数据; //设置一个flag来表示技术如何加入队列中 queue<TreeNode *> result; vector<vector<int>> ans; if(root==NULL){ return ans; } int flag=1; result.push(root); while(!result.empty()){ queue<TreeNode*> temp; vector<int> tempVector; while(!result.empty()){ TreeNode *top=result.front(); result.pop(); tempVector.push_back(top->val); if(top->left!=NULL){ temp.push(top->left); } if(top->right!=NULL){ temp.push(top->right); } } if(flag==1){ ans.push_back(tempVector); flag=0;} else{ reverse(tempVector.begin(),tempVector.end()); ans.push_back(tempVector); flag=1;} result=temp;} return ans; } };