LeetCode刷题

目录

 一、栈

逆波兰表达式求值

什么是逆波兰表达式?

解题思路

代码

二、二叉树

(一)根据二叉树创建字符串

解题思路

(二)二叉树的层序遍历

怎么垂直遍历这个树

(三)二叉树的最近公共祖先

解题思路

(四)搜索二叉树与双向链表

解题思路

(五)二叉树的前序遍历

解题思路

递归实现

进阶:非递归实现

(六)二叉树的中序遍历

解题思路

递归实现

(七)二叉树的后序遍历

解题思路

递归实现

(八)前K个高频单词

解题思路


 一、栈

逆波兰表达式求值

​​​​zz. - 力扣(LeetCode)

什么是逆波兰表达式?

逆波兰表达式,也就是后缀表达式,就是将操作符都放到最后

例如1+2*3 的逆波兰表达式就是 1 2 3 + *

解题思路

   

利用栈st,将tokens依次入栈,

首先入栈2,但是要将字符串2转为整数2,因此用到stoi()这个字符串方法,

再将1入栈

后面检查到操作符"+"

就把栈中的st依次出栈,(出栈顺序为从右往左),将运算结果再压入栈中,再继续把没压入栈st中的tokens剩余字符串压入栈,直到遍历完整个tokens,最后的结果就留在了栈st中。

代码
class Solution {
public:
    int evalRPN(vector<string>& tokens) {
        stack<int> st;
        for(auto str : tokens)
        {
            if(str=="+"||str=="-"||str=="*"||str=="/")
            {
                int right = st.top();
                st.pop();
                int left = st.top();
                st.pop();
                //注意这里不能用str
                switch(str[0])
                {
                    case '+':
                        st.push(right+left);
                        break;
                    case '-':
                        st.push(left-right);
                        break;
                    case '*':
                        st.push(left*right);
                        break;
                    case '/':
                        st.push(left/right);
                        break;
                }
            }
            else
            {
                st.push(stoi(str));
            }
        }

        return st.top();

    }
};

二、二叉树

(一)根据二叉树创建字符串

. - 力扣(LeetCode)

这里需要注意的是,当左子树为空,就要判断右子树是不是存在,如果存在则左子树要有括号,如果右子树不存在则不需要括号,

解题思路

这里的关键是怎么遍历这个树,然后这里要的是前序遍历,那么访问顺序就是中左右,利用递归可以很好的遍历这个树,

class Solution {
public:
    string tree2str(TreeNode* root) {
        string s1="";
        if(root==nullptr)
        {
            return "";
        }
        s1+=to_string(root->val);
        if(root->left)
        {
            s1+="(";
            s1+=tree2str(root->left);
            s1+=")";
        }
        else if(root->right)
        {
            s1+="()";
        }
        if(root->right)
        {
            s1+="(";
            s1+=tree2str(root->right);
            s1+=")";
        }
        return s1;
    }
};

(二)二叉树的层序遍历

. - 力扣(LeetCode)

怎么垂直遍历这个树

利用一个队列queue<TreeNode*> q

先看这个树是不是为空如果是则直接返回

否则将根压入队列

然后循环这个队列看队列是否是空,不是空那么弹出这个队列,计算队列中的大小,也就相当于每一层有多少个元素,

利用vector<int> v 装这层的数据,

然后如果该节点的左右子树存在那么压入队列

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {

        vector<vector<int>> vv;

        queue<TreeNode*> q;
        if(!root)
        {
            return vv;
        }
        if(root)
        {
            q.push(root);
        }
        
        while(!q.empty())
        {
            int size=q.size();
            vector<int> v;
            for(int i=0;i<size;i++)
            {
                TreeNode* front=q.front();
                v.push_back(front->val);
                q.pop();

                if(front->left)
                {
                    q.push(front->left);
                }
                if(front->right)
                {
                    q.push(front->right);
                }
            }
            vv.push_back(v);
            
        }
        return vv;
    }
};

(三)二叉树的最近公共祖先

. - 力扣(LeetCode)

解题思路

(1)如果p和q在root的左右子树中说明root就是他们的最近祖先

(2)如果p和q都在左子树中,那么找离顶最近的那个就是祖先

class Solution {
public:

    bool Find(TreeNode* root,TreeNode* x)
    {
        if(root==NULL)
            return false;

        return root == x
            || Find(root->left,x)
            || Find(root->right,x);
    }


    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        
        bool pInRight,pInLeft,qInRight,qInLeft;
        if(root==NULL)
        {
            return NULL;
        }
        if(root==p||root==q)
        {
            return root;
        }

        pInRight=Find(root->right,p);
        pInLeft=!pInRight;

        qInRight=Find(root->right,q);
        qInLeft=!qInRight;

        if((pInLeft&&qInRight)||(qInLeft&&pInRight))
        {
            return root;
        }
        if(pInLeft&&qInLeft)
        {
            return lowestCommonAncestor(root->left,p,q);
        }
        if(pInRight&&qInRight)
        {
            return lowestCommonAncestor(root->right,p,q);
        }

        return NULL;
    }
};

(四)搜索二叉树与双向链表

二叉搜索树与双向链表_牛客题霸_牛客网

解题思路

一个二叉树的中序遍历是有序的,并且遍历的实现是递归,但是递归并不知道上一个节点,因此就要想办法找到上一个节点,因此我们使用指针的引用,TreeNode* & prev 需要注意这里是引用,用来修改prev的值,

class Solution {
public:
                                    //这里是指针的引用
	void ConvertList(TreeNode* cur,TreeNode*& prev)
	{
		if(cur==NULL)
		{
			return ;
		}
		//一直找到最第一个节点,因为是中序就是最左边的那个先遍历所以先找到最左边那个
		ConvertList(cur->left,prev);
		//让当前的左节点指向上一个节点
		cur->left=prev;
		//如果是第一次prev为NULL那么不做操作
		if(prev)
		{
			//让上一次的节点的右节点指向下一个节点
			prev->right=cur;
		}
		//把prev指向上一个节点
		prev=cur;
		//然后遍历右边的子树
		ConvertList(cur->right,prev);
	}

    TreeNode* Convert(TreeNode* pRootOfTree) {
        TreeNode* prev=NULL;
		ConvertList(pRootOfTree,prev);

		//找到链表的头,链表的头就是最左边子树
		TreeNode* head=pRootOfTree;
		//这里为什么要判断head!=NULL是因为如果这个树为空那么不操作
		while(head&&head->left)
		{
			head=head->left;
		}
		return head;
    }
};

(五)二叉树的前序遍历

. - 力扣(LeetCode)

解题思路
递归实现

递归实现很简单就是遍历完根后遍历左子树,再遍历右子树

class Solution {
public:
    void _preorderTraversal(TreeNode* root,vector<int> & v)
    {
        if(!root)
        {
            return;
        }
        v.push_back(root->val);
        _preorderTraversal(root->left,v);
        _preorderTraversal(root->right,v);     
    }
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> v;
        _preorderTraversal(root,v);
        return v;
    }
};

进阶:非递归实现

其实递归就像栈一样,因此非递归就是让我们模拟栈,

/**
 * 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:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> v;
        stack<TreeNode*> st;
        TreeNode* cur=root;
        //如果栈为空说明遍历完了,如果cur为空说明这个节点为空
        while(cur||!st.empty())
        {
            //一直往左遍历,
            while(cur)
            {
                //先把当前的值存入v
                v.push_back(cur->val);
                //把现在的cur入栈
                st.push(cur);
                cur=cur->left;
            }
            //说明左边的节点访问完了,那么就开始右节点的访问先弹出栈顶元素,就是最后一个左节点
            TreeNode* tp=st.top();
            st.pop();
            //然后让当前的cur指向右节点去访问,再进行大循环,遍历这个节点的左节点
            cur=tp->right;
        }
        return v;
    }
};

(六)二叉树的中序遍历

. - 力扣(LeetCode)

解题思路
递归实现

就是正常的左中右遍历递归思路

class Solution {
public:
    void _inorderTraversal(TreeNode* root,vector<int>& v)
    {
        if(!root)
        {
            return ;
        }
        _inorderTraversal(root->left,v);
        v.push_back(root->val);
        _inorderTraversal(root->right,v);
    }
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> v;
        _inorderTraversal(root,v);
        return v;
    }
};

非递归实现

思路和前序遍历一样,只不过是在遍历完左节点之后插入的值

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> v;
        stack<TreeNode*> st;
        TreeNode* cur=root;
        while(cur||!st.empty())
        {
            while(cur)
            {
                st.push(cur);
                cur=cur->left;
            }
            
            TreeNode* tp=st.top();
            st.pop();
            v.push_back(tp->val);
            cur=tp->right;
        }
        return v;
    }
};

(七)二叉树的后序遍历

. - 力扣(LeetCode)

解题思路
递归实现

思路和前面的前序遍历和中序遍历一样但是顺序改变了

class Solution {
public:
    void _postorderTraversal(TreeNode* root,vector<int>& v)
    {
        if(!root)
        {
            return ;
        }
        _postorderTraversal(root->left,v);
        _postorderTraversal(root->right,v);
        v.push_back(root->val);
    }
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> v;
        _postorderTraversal(root,v);
        return v;
    }
};

(八)前K个高频单词

. - 力扣(LeetCode)

解题思路
class Solution {
public:
    vector<string> topKFrequent(vector<string>& words, int k) {
        map<string,int> countMap;
        vector<string> v;
        //遍历这个字符串容器,看看每个单词出现的次数
        for(auto e: words)
        {
            countMap[e]++;
        }
        //根据次数然后排序,如果用sort的话可能不能正确实现字符的大小正确,因为sort的底层是快排
        //multimap可以解决这个问题,
        //但是multimap<int,string,less<int>>默认这里是升序的,所以输出的结果是
        //coding , leetcode , i , love
        //很明显不满足要求
        //因此把less<int>按照键的要求从大往小排
        
        multimap<int,string,greater<int>>sortMap;
        for(auto kv:countMap)
        {
            sortMap.insert(make_pair(kv.second,kv.first));
        }
        auto it=sortMap.begin();
        while(it!=sortMap.end())
        {
            if(k==0)
            {
                break;
            }
            v.push_back(it->second);
            ++it;
            --k;
        }
        return v;
    }
};

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值