剑指OFFER21-30题

21栈的压入、弹出序列
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)

class Solution {
public:
    stack<int> sk;
    bool IsPopOrder(vector<int> pushV,vector<int> popV) {
        int i,j=0;
        for(i=0;i<pushV.size();i++){
            sk.push(pushV[i]);
            while( !sk.empty() && sk.top()==popV[j] ){
                sk.pop();
                j++;
                if(j>=popV.size())return true;
            }
        }
        return false;
    }
};

22从上往下打印二叉树
从上往下打印出二叉树的每个节点,同层节点从左至右打印。

/*
struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) :
			val(x), left(NULL), right(NULL) {
	}
};*/
class Solution {
public:
    queue<TreeNode*> qe;
    vector<int> PrintFromTopToBottom(TreeNode* root) {
        vector<int> ans;
        if(root==NULL)return ans;
        qe.push(root);
        while(!qe.empty()){
            TreeNode* tmp=qe.front();
            qe.pop();
            ans.push_back(tmp->val);
            if(tmp->left!=NULL)qe.push(tmp->left);
            if(tmp->right!=NULL)qe.push(tmp->right);
        }
        return ans;
        
    }
};

23二叉搜索树的后序遍历序列
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。

class Solution {
public:
    vector<int> t;//全局
    bool dfs(int l,int r){//传入左右界
        if(l>r)return true;//区间无值即为真
        //从左扫找到父结点位置
        int i,val=t[r];//循环变量,及右界为父节点值
        for(i=l;i<=r-1;i++){//扫一次
            if(t[i]>val){//一旦发现有大于的就跳出
                break;
            }
        }
        //判断右子树是否符合,不符就返回假
        for(int j=i;j<=r-1;j++){//从上面扫到的位置开始
            if(t[j]<val){//如果有小于就为假
                return false;
            }
        }
        //返回左右子树递归的结果与
        return ( dfs(l,i-1) && dfs(i+1,r-1) );
    }

    bool VerifySquenceOfBST(vector<int> sequence) {
        t=sequence;//复制
        if( t.size()==0 )return false;//只有0个或1个数就跳出吧
        if( t.size()==1 )return true;//只有0个或1个数就跳出吧
        return dfs(0,t.size()-1);//传入左右界深搜
    }
};

24二叉树中和为某一值的路径
输入一颗二叉树的跟节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。(注意: 在返回值的list中,数组长度大的数组靠前)

/*
struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) :
			val(x), left(NULL), right(NULL) {
	}
};*/
class Solution {
public:
    
    vector<vector<int> > ans;
    static bool cmp(vector<int> a,vector<int> b){
        return a.size()>b.size();
    }
    vector<int> t;
    void dfs(TreeNode* r,int target,int now){
        if(r==NULL)return ;
        t.push_back(r->val);
        if(now+r->val>target){
            return ;
        }
        if(now+r->val==target && r->left==NULL && r->right==NULL){
            ans.push_back(t);
        }
        if(now<target){
            if(r->left!=NULL)dfs(r->left,target,now+r->val);
            if(r->right!=NULL)dfs(r->right,target,now+r->val);
            t.resize(t.size()-1);//只是退出当前结点时才需要把结点从路径移除
        }
    }
    vector<vector<int> > FindPath(TreeNode* root,int expectNumber) {
        dfs(root,expectNumber,0);
        sort(ans.begin(),ans.end(),cmp);
        return ans;
    }
};

25复杂链表的复制
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)

/*
struct RandomListNode {
    int label;
    struct RandomListNode *next, *random;
    RandomListNode(int x) :
            label(x), next(NULL), random(NULL) {
    }
};
*/
class Solution {
public:
    RandomListNode* Clone(RandomListNode* pHead){
        if (pHead == NULL) {
            return NULL;
        }
        RandomListNode* head = new RandomListNode(-1); // 头指针;
        RandomListNode* q = head;
        RandomListNode* p = pHead;
        // 先不管random
        while (p != NULL) {//
            RandomListNode* newNode = new RandomListNode(p->label); // 新节点;
            q->next = newNode;
            q = q->next;
            p = p->next;
        }
        // 重新设置random指针;
        q = head;
        p = pHead;
        RandomListNode* k = head->next;
        while (p != NULL) { //间接表示q.next!=null;
            if(p->random==NULL) { //指向null;
                k=NULL;
            }else {
                k=head->next;
            }
            while (k != NULL && k->label != p->random->label) {
                k=k->next;
            }
            //一定存在;
            q->next->random = k;
            p=p->next;
            q=q->next;
        }
        return head->next;
    }
};

26二叉搜索树与双向链表
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。

/*
struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) :
			val(x), left(NULL), right(NULL) {
	}
};*/
class Solution {
public:
    stack<TreeNode* >st;
    void vis(TreeNode* pre,TreeNode* now){
        now->left=pre;
        if(pre!=NULL){
            pre->right=now;
            pre=now;
        }
    }
    TreeNode* Convert(TreeNode* pRootOfTree){
        if(pRootOfTree==NULL)return NULL;//判空
        TreeNode* head;int flag=0;//用于返回
        TreeNode* pre=NULL;
        TreeNode* p=pRootOfTree;
        while(p!=NULL||!st.empty()){
            while(p!=NULL){
                st.push(p);
                p=p->left;  
            }
             if(!st.empty()){
                 p=st.top();
                 if(flag==0){head=p;flag=1;}
                 st.pop();
                 vis(pre,p);
                 pre=p;
                 p=p->right;
             }
        }
        pre->right=NULL;
        return head;
    }
};

27字符串的排列
题目描述
输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
输入描述:
输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。

class Solution {
public:
    vector<string> Permutation(string str) {
        vector<string> s;
        if(str.empty())return s;
        int len=str.size();
        char ss[len+1];
        for(int i=0;i<len;i++){
            ss[i]=str[i];
        }
        ss[len]='\0';
        sort(ss,ss+len);
        s.push_back(ss);
        while(next_permutation(ss,ss+len))
        {
            s.push_back(ss);
        }
        return s;
    }
};

28数组中出现次数超过一半的数字
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。

class Solution {
public:
    int MoreThanHalfNum_Solution(vector<int> numbers) {
        sort(numbers.begin(),numbers.end());//sort
        int len=numbers.size();//len
        int val[len],tot[len],cnt=0;//val,tot,cnt
        val[cnt]=numbers[0];//0
        tot[cnt]=1;//0
        for(int i=1;i<len;i++){
            if(numbers[i]==val[cnt]){//if --
                tot[cnt]++;//tot++
            }
            else{//if !=
                val[++cnt]=numbers[i];//cnt+1
                tot[cnt]=1;//1
            }
        }
        int mx=-1,mxid=-1;
        for(int i=0;i<=cnt;i++){
            if( mx<tot[i] && tot[i]>len/2 ){
                mx=tot[i];
                mxid=i;
            }
        }
        return val[mxid];
    }
    //要存出现的每个数以及每个数出现的次数
    //然后扫一次得次数量大值,然后再扫一次看是否有跟次数最大值相同,有则0,没有就利用该次数最大值的下标输出答案
    
};

29最小的K个数
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。

class Solution {
public:
    vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
        vector<int> ans;
        if(input.size()<k)return ans;
        sort(input.begin(),input.end());
        for(int i=0;i<k;i++){
            ans.push_back(input[i]);
        }
        return ans;
    }
};

30连续子数组的最大和
HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。给一个数组,返回它的最大连续子序列的和,你会不会被他忽悠住?(子向量的长度至少是1)

class Solution {
public:
    int FindGreatestSumOfSubArray(vector<int> array) {
        int ans=array[0],now=0;
        for(int i=0;i<array.size();i++){
            now+=array[i];
            ans=ans>now?ans:now;
            if(now<0)now=0;
        }
        return ans;
    }
};

猜你喜欢

转载自blog.csdn.net/cj1064789374/article/details/85010786