剑指Offer_C++题解2

文章目录

      • 二叉树的镜像
      • 顺时针打印矩阵
      • 包含min函数的栈
      • 栈的压入弹出序列
      • 从上往下打印二叉树
      • 二叉树的后序遍历序列
      • 二叉树中和为某一值的路径
      • 复杂链表的复制
      • 二叉搜索树与双向链表
      • 字符串的排列

二叉树的镜像

题目描述
操作给定的二叉树,将其变换为源二叉树的镜像。
输入描述:
二叉树的镜像定义:源二叉树
8
/
6 10
/ \ /
5 7 9 11
镜像二叉树
8
/
10 6
/ \ /
11 9 7 5

/*
struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) :
			val(x), left(NULL), right(NULL) {
	}
};*/
class Solution {
public:
    void Mirror(TreeNode *pRoot) {
        if(pRoot == NULL)
            return;
        if((pRoot -> left == NULL) && (pRoot -> right == NULL))
            return;
           
        TreeNode *temp = pRoot -> left;
        pRoot -> left = pRoot -> right;
        pRoot -> right = temp;
        
        if(pRoot -> left)
            Mirror(pRoot -> left);
        if(pRoot -> right)
            Mirror(pRoot -> right);
    }
};

顺时针打印矩阵

题目描述
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.

//解1
class Solution {
public:
    vector<int> printMatrix(vector<vector<int> > matrix) {
        vector<int> res;
        int row = matrix.size();
        int col = matrix[0].size();
        
        if(row == 0 || col == 0)
            return res;
        
        int left = 0,right = col - 1,top = 0,bottom = row - 1;
        while(left <= right && top <= bottom){
            for(int i = left;i <= right;++i)
                res.push_back(matrix[top][i]);
            for(int i = top+1;i <= bottom;++i)
                res.push_back(matrix[i][right]);
            if(top != bottom)
            for(int i = right-1;i >= left;--i)
                res.push_back(matrix[bottom][i]);
            if(left != right)
            for(int i = bottom-1;i > top; --i)
                res.push_back(matrix[i][left]);
            
            left++;right--;top++;bottom--;
        }
        return res;
    }
};

//解2
class Solution {
public:
    vector<int> printMatrix(vector<vector<int> > matrix) {
        int row = matrix.size();
        int col = matrix[0].size();
        vector<int> res;
         
        // 输入的二维数组非法,返回空的数组
        if (row == 0 || col == 0)  return res;
         
        // 定义四个关键变量,表示左上和右下的打印范围
        int left = 0, top = 0, right = col - 1, bottom = row - 1;
        while (left <= right && top <= bottom)
        {
            // left to right
            for (int i = left; i <= right; ++i)  res.push_back(matrix[top][i]);
            // top to bottom
            for (int i = top + 1; i <= bottom; ++i)  res.push_back(matrix[i][right]);
            // right to left
            if (top != bottom)
            for (int i = right - 1; i >= left; --i)  res.push_back(matrix[bottom][i]);
            // bottom to top
            if (left != right)
            for (int i = bottom - 1; i > top; --i)  res.push_back(matrix[i][left]);
            left++,top++,right--,bottom--;
        }
        return res;
    }
};

包含min函数的栈

class Solution {
public:
    stack<int> data,m_min;
        
    void push(int value) {
        data.push(value);
        if(m_min.empty()||value<m_min.top())
            m_min.push(value);
        else
            m_min.push(m_min.top());
        
    }
    void pop() {
        //assert(data.size()>0&&m_min.size()>0);
        
        data.pop();
        m_min.pop();
    }
    int top() {
        return data.top();
    }
    int min() {
       // assert(data.size()>0&&m_min.size()>0);
        return m_min.top();
    }
};

栈的压入弹出序列

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

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

从上往下打印二叉树

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

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

二叉树的后序遍历序列

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

class Solution {
public:
    bool VerifySquenceOfBST(vector<int> sequence) {
        if(sequence.empty())
            return false;
        int len = sequence.size();
        int root = sequence.back();
        int i=0;
        vector<int> left,right;
        for(;i<len-1;i++){
            if(sequence[i]>root)
                break;
            else left.push_back(sequence[i]);
        }

        for(int j=i;j<len-1;j++){
            if(root>sequence[j])
                return false;
            else right.push_back(sequence[j]);
        }
        
        bool l = true;
        if(left.size())
            l = VerifySquenceOfBST(left);
        
        bool r = true;
        if(right.size())
            r = VerifySquenceOfBST(right);
        
        return (l&&r);
    }
};

二叉树中和为某一值的路径

题目描述
输入一颗二叉树的跟节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。(注意: 在返回值的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> > res;
    vector<int> path;

    vector<vector<int> > FindPath(TreeNode* root,int expectNumber) {
        if(root == NULL)
            return res;
        findpath(root,expectNumber);
        return res;
    }
    
    void findpath(TreeNode* root,int sum){
        path.push_back(root->val);
        if(root->left == NULL && root->right == NULL && sum == root->val)
            res.push_back(path);
        if(root->left)
            findpath(root->left,sum-root->val);
        if(root->right)
            findpath(root->right,sum-root->val);
        path.pop_back();
    }
};

复杂链表的复制

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

/*
struct RandomListNode {
    int label;
    struct RandomListNode *next, *random;
    RandomListNode(int x) :
            label(x), next(NULL), random(NULL) {
    }
};
*/
//解1
class Solution {
public:
    
    //第一步:复制到一个链表
    void CloneNodes(RandomListNode* pHead){
        RandomListNode* pNode = pHead;
        while(pNode!=NULL){
            RandomListNode* pClone = new RandomListNode(0);
            pClone->next = pNode->next;
            pClone->label = pNode->label;
            pClone->random = NULL;
            
            pNode->next = pClone;
            pNode=pClone->next;
            
        }
    }
    //第二步:random指向
    void CloneRandom(RandomListNode* pHead){
        RandomListNode* pNode = pHead;
        while(pNode!=NULL){
            RandomListNode* pClone = pNode->next;
            if(pNode->random!=NULL){
                pClone->random = pNode->random->next;
            }
            pNode=pClone->next;
        }
    }
    
    //第三步:拆分
    RandomListNode* Reconnect(RandomListNode* pHead){
        RandomListNode* pNode = pHead;
        RandomListNode* pCloneNode = NULL;
        RandomListNode* pCloneHead = NULL;
        
        if(pNode){
            pCloneHead = pCloneNode = pNode->next;
            pNode->next = pCloneHead->next;
            pNode = pNode->next;
        }
        while(pNode){
            pCloneNode->next = pNode->next;
            pCloneNode = pCloneNode->next;
            pNode->next = pCloneNode->next;
            pNode=pNode->next;
        }
        return pCloneHead;
    }
    
    RandomListNode* Clone(RandomListNode* pHead){
        CloneNodes(pHead);
        CloneRandom(pHead);
        return Reconnect(pHead);
        
    }
    
    
};

//解2
class Solution {
public:
    /*
        1、复制每个节点,如:复制节点A得到A1,将A1插入节点A后面
        2、遍历链表,A1->random = A->random->next;
        3、将链表拆分成原链表和复制后的链表
    */
     
    RandomListNode* Clone(RandomListNode* pHead)
    {
        if(!pHead) return NULL;
        RandomListNode *currNode = pHead;
        while(currNode){
            RandomListNode *node = new RandomListNode(currNode->label);
            node->next = currNode->next;
            currNode->next = node;
            currNode = node->next;
        }
        currNode = pHead;
        while(currNode){
            RandomListNode *node = currNode->next;
            if(currNode->random){               
                node->random = currNode->random->next;
            }
            currNode = node->next;
        }
        //拆分
        RandomListNode *pCloneHead = pHead->next;
        RandomListNode *tmp;
        currNode = pHead;
        while(currNode->next){
            tmp = currNode->next;
            currNode->next =tmp->next;
            currNode = tmp;
        }
        return pCloneHead;
    }
};

二叉搜索树与双向链表

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

/*
struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) :
			val(x), left(NULL), right(NULL) {
	}
};*/
class Solution {
public:
    TreeNode* Convert(TreeNode* pRootOfTree)
    {
        if(pRootOfTree == nullptr)
            return nullptr;
        TreeNode* pre = nullptr;
        
        ConvertNode(pRootOfTree,pre);
        
        TreeNode* res = pRootOfTree;
        while(res->left)
            res = res->left;
        return res;
    }
    
    void ConvertNode(TreeNode* cur,TreeNode*& pre){
        if(cur == nullptr)
            return;
        ConvertNode(cur->left,pre);
        cur->left = pre;
        if(pre) pre->right = cur;
        pre = cur;
        ConvertNode(cur->right,pre);
        
    }
};

字符串的排列

题目描述
输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。

class Solution {
public:
    void Permutation(vector<string>& array,string str,int begin){
        if(begin == str.size()-1)
            array.push_back(str);
        for(int i=begin;i<=str.size()-1;i++){
            if(i!=begin && str[i]==str[begin])
                continue;
            swap(str[i],str[begin]);
            Permutation(array,str,begin+1);
            swap(str[i],str[begin]);
        }
    }
    
    vector<string> Permutation(string str) {
        vector<string> array;
        if(str.size() == 0)
            return array;
        Permutation(array,str,0);
        sort(array.begin(),array.end());
        return array;
    }
};

你可能感兴趣的:(数据结构与算法)