剑指offer习题集2

1.把数组排成最小的数

class Solution {
public:
     
    static bool compare(const string& s1, const string& s2) {  
        string t1 = s1 + s2;   
        string t2 = s2 + s1;
        return t1 <= t2? true : false;
    }
     
    string PrintMinNumber(vector<int> numbers) {
     
        string str;
        int i, len = numbers.size();   
        if (len<1) return str;
     
        string res;
        vector<string> vt;
        for (i = 0;i<len;++i) { 
            stringstream stream;       
            stream << numbers[i];    
            stream >> str;       
            vt.push_back(str);
        }
     
        sort(vt.begin(), vt.end(), compare);   
        for (i = 0;i<len;++i)       
            res += vt[i];  
        return res;
    }
};
View Code

这里使用string会比使用char*更加快捷方便。

另外使用sort而不是qsort,主要是sort是qsort的升级,且参数更少,不需要制定每个参数占据的内存空间大小。

 

2.字符流中第一个不重复的字符

少有的一遍通过的程序,眼泪都快流下来了

class Solution
{
public:
    
    Solution():index(0){ //初始化位置
        for(int i=0;i<256;++i)
            pos[i]=-1;
    }
    
    
  //Insert one char from stringstream
    void Insert(char ch)
    {
         if(pos[ch]==-1)
             pos[ch]=index;
         else if(pos[ch]>=0)
             pos[ch]=-2;
             
         ++index;
    }
    
    
  //return the first appearence once char in current stringstream
    char FirstAppearingOnce()
    {  
        char res='#';
        int minv=1e8,i; //设置字符串max值
        for(i=0;i<256;++i){
            if(pos[i]>=0&&pos[i]<minv){ //若是当前位置小于min,则对min进行更新
                res=(char)i;
                minv=pos[i];
            }  
        }
        
        return res;
    }
    
private:
    int index;
    int pos[256];
};
View Code

 

3.求滑动窗口最大值

还是不能一遍通过,而且思维定式,真的很难找到错误的

class Solution {
public:
    vector<int> maxInWindows(const vector<int>& num, unsigned int size)
    {
        int i,j,k,len=num.size();
        vector<int> result;
        if(len<size||size==0) 
            return result;
        
        int max=num[0];
        for(i=1;i<size;++i){ //先寻找第一个窗口的最大值
            if(max<num[i])
                max=num[i];
        }
        result.push_back(max);
        
        for(i=1;i<=(len-size);++i){
            j=i+size-1;
            if(num[j]<max){
                //判断最大值是否移出滑动窗口
                if(num[i-1]!=max)
                    result.push_back(max);
                else{ //确定最大值被移出滑动窗口,重新确定最大值
                    max=num[i];
                    for(k=i;k<=j;++k){
                        if(num[k]>max)
                            max=num[k];
                    }
                    result.push_back(max);
                }
            }else{
                result.push_back(num[j]);
                max=num[j];
            }               
        }
        return result;
    }
};
View Code

 

4.表示数值的字符串(最耗人心力的程序,没有之一)

有空多做几遍,绝对练耐心

class Solution {
public:
    
    bool isdigit(const char& ch){
        if(ch<='9'&&ch>='0')
            return true;
        else return false;
    }
    
    void scandigits(char** str){
        while(**str!='\0'&&isdigit(**str))
            ++(*str);
    }
    
    bool isexpand(char** str){
        if(**str!='E'&&**str!='e')
            return false;
        
        ++(*str);
        if(**str=='+'||**str=='-')
            ++(*str);
        
        if(**str=='\0')
            return false;
        
        scandigits(str);
        return (**str=='\0')?true:false;
    }
    
    bool isNumeric(char* strt)
    {
        if(NULL==strt)
            return false;
        
        bool digit=true;
        char *str=strt;
        
        //排除符号干扰,找到第一个数字
        while(str){
            if(*str=='+'||*str=='-'){
                ++str;break;
            }else if(isdigit(*str)){
                break; //找到第一个数字
            }
        }
        if(*str=='\0') return false;
        
        scandigits(&str);
        if(*str!='\0'){
            //针对小数进行处理
            if(*str=='.'){
                ++str;
                scandigits(&str);
                
                if(*str=='e'||*str=='E')
                    digit=isexpand(&str);
            }else if(*str=='E'||*str=='e'){
                digit=isexpand(&str);  
            }else{
                digit=false;
            }
        }
         
        return digit&&(*str=='\0');
    }

};
View Code

 

5.字符串的排列

《剑指offer》上针对的是无重复字符串的全排列递归做法。

下面贴的是对重复字符进行处理了的全排列递归做法,为了通过测试集,对字符串进行了排序。

class Solution {
public:
     
    vector<string> Permutation(string str) {
         
        vector<string> res;
        int len=str.length();
        if(0==len) return res;
        else if(1==len){
            res.push_back(str); return res;
        }
         
        int left=0,right=len-1;
        Permutation(str,left,right,res);
        sort(res.begin(),res.end());
        return res;
    }
     
    //递归实现字符交换
    void Permutation(string& str,int left,int right,vector<string>& res){
         
        if(left==right){
            res.push_back(str);
        }else{
            for(int i=left;i<=right;++i){
                if(isswap(str,left,i)){
                    swap(str[i],str[left]);
                    Permutation(str,left+1,right,res);
                    swap(str[i],str[left]);
                }
            }
        }
    }
     
private:
    void swap(char& a,char& b){
        char t=a;a=b;b=t;
    }
     
    bool isswap(const string& str,const int& left,const int& right){
        for(int i=left;i<right;++i)
            if(str[i]==str[right])
                return false;
        return true;
    } 
};
View Code

后续会添加相应的非递归做法。

另外,此题可以扩展为多个子问题,待后续一一解决。

 

6.求旋转数组的最小数

没有通过测试集,不过自行调试,觉得程序应该是正确的啊

class Solution {
public:
    int minNumberInRotateArray(vector<int> rotateArray) {

        int len = rotateArray.size();
        if (0 == len) return 0;
        else if (1 == len) return rotateArray[0];

        int left = 0, right = len - 1, mid;
        while (rotateArray[left] >= rotateArray[right]) {

            if (right - left == 1) {
                mid = right;break;
            }

            mid = left + (right - left) / 2;

            //如果下标为left/right/mid指向的三个数字相等
            if (rotateArray[left] == rotateArray[right] &&
                rotateArray[left] == rotateArray[mid]) {
                //顺序查找最小元素
                return mininorder(rotateArray, left, right);
            }

            if (rotateArray[mid] >= rotateArray[left]) {
                left = mid;
            }
            else if (rotateArray[mid] <= rotateArray[right]) {
                right = mid;
            }
        }

        return rotateArray[mid];
    }

private:
    int mininorder(const vector<int>& rotateArray, const int& left, const int& right) {
        int min = rotateArray[left];
        for (int i = left + 1;i <= right;++i) {
            if (rotateArray[i]<min)
                min = rotateArray[i];
        }
        return min;
    }
};
View Code

 

7.扑克牌顺子

class Solution {
public:
    bool IsContinuous( vector<int> numbers ) {
        
        int len=numbers.size();
        if(len<=1) return false;
        
        //进行排序
        sort(numbers.begin(),numbers.end());
        
        int i=0,zeronum=0,gap,numgap=0;
        for(i=0;i<len;i++){
            if(numbers[i]==0)
                ++zeronum;
            else break;
        }
        
        //从非零的下一个位置开始进行计算
        for(i=i+1;i<len;++i){
            gap=numbers[i]-numbers[i-1];
            if(0==gap)
                return false;
            else if(1==gap)
                continue;
            else{
                numgap+=gap-1;
            }
        }
        
        if(numgap<=zeronum)
            return true;
        else return false;
    }
};
View Code

 

8.丑数

此题真的不太好理解,需要重复练习几遍方能理解贯通。

class Solution {
public:
    int GetUglyNumber_Solution(int index) {
         
        if(0==index) return 0;
        else if(1==index) return 1;
             
        long long *uglynum=new long long[index];
        uglynum[0]=1;
        int nextuglyindex=1;
         
        long long min,*p1=uglynum,*p2=uglynum,*p3=uglynum;
        while(nextuglyindex<index){
            min=minnum(*p1*2,*p2*3,*p3*5);
            uglynum[nextuglyindex]=min;
             
            while(*p1*2<=uglynum[nextuglyindex])
                ++p1;
            while(*p2*3<=uglynum[nextuglyindex])
                ++p2;
            while(*p3*5<=uglynum[nextuglyindex])
                ++p3;
             
            ++nextuglyindex;
        }
         
        int res= (int)uglynum[nextuglyindex-1];
        delete[] uglynum;
        return res;
    }
     
private:
    long long minnum(const long long& num1,const long long& num2,const long long& num3){
        long long min=(num1<num2)?num1:num2;
        return (num3<min)?num3:min;
    }
};
View Code

 

9.正则表达式匹配

class Solution {
public:
    bool match(char* str, char* pattern)
    {
        if(NULL==str||pattern==NULL)
            return false;
        else return matchstr(str,pattern);
    }
     
private:
    bool matchstr(char* str,char* pattern){
         
        if(*str=='\0'&&*pattern=='\0')
            return true;
         
        if(*str!='\0'&&*pattern=='\0')
            return false;
         
        if(*(pattern+1)=='*'){
            if(*pattern==*str||(*pattern=='.'&&*str!='\0'))
                return    matchstr(str+1,pattern+2)
                       || matchstr(str+1,pattern)
                       || matchstr(str,pattern+2);
            else return matchstr(str,pattern+2);   
        }
         
        if(*str==*pattern||(*pattern=='.'&&*str!='\0'))
            return matchstr(str+1,pattern+1);
         
        return false;
    }
};
View Code

return使用||返回几个可能结果,状态之间的变化,简直不能再赞了

 

10.树的子结构

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};*/
class Solution {
public:
    bool HasSubtree(TreeNode* root1, TreeNode* root2)
    {
        bool res=false;
        
        if(root1!=NULL&&root2!=NULL){
            if(root1->val==root2->val){
                res=judgetree(root1,root2);
            }
            if(!res)
                res=HasSubtree(root1->left,root2);
            if(!res)  
                res=HasSubtree(root1->right,root2);
        }
        
        return res;
    }
    
private:
    bool judgetree(TreeNode* root1, TreeNode* root2){
        if(root2==NULL)
            return true;
        
        if(root1==NULL)
            return false;
        
        if(root1->val!=root2->val)
            return false;
        
        return judgetree(root1->left,root2->left)&&
            judgetree(root1->right,root2->right);
    }
};

以后看看能不能改进,避免递归调用。

 

11.栈的压入弹出

class Solution {
public:
    bool IsPopOrder(vector<int> push, vector<int> pop) {

        bool res = false;
        int len = push.size();
        if (len != pop.size() || len <= 0) return res;

        stack<int> sdata;
        vector<int>::iterator nextpush = push.begin(), nextpop = pop.begin();

        while (nextpop - pop.begin() < len)
        {
            while (sdata.empty() || sdata.top() != *nextpop)
            {
                if (nextpush - push.begin() == len)
                    break;

                sdata.push(*nextpush);

                ++nextpush;
            }

            if (sdata.top() != *nextpop)
                break;

            sdata.pop();
            nextpop++;
        }

        if (sdata.empty() && nextpop - pop.begin() == len)
            res = true;

        return res;
    }
};

 

12.二叉搜索树的后序遍历序列

class Solution {
public:
    bool VerifySquenceOfBST(vector<int> sdata) {

        int len = sdata.size();
        if (len <= 0) return false;

        return judgeBST(sdata, 0, len - 1);
    }

private:
    bool judgeBST(vector<int>& sdata, int left, int right) {

        if (right - left < 0) return false;

        int i, j, root = sdata[right];

        for (i = left;i < right;++i) {
            if (sdata[i] > root)
                break;
        }

        for (j = i;j < right;++j) {
            if (sdata[j] < root)
                return false;
        }

        bool leftsign = true, rightsign = true;
        if (i > left)  //表示有左子树
            leftsign = judgeBST(sdata, left, i - 1);

        if (i < right) //表示有右子树
            rightsign = judgeBST(sdata, i, right - 1);

        return (leftsign&&rightsign);
    }
};

 

13.按之字形顺序打印二叉树

class Solution {
public:
    vector<vector<int>> Print(TreeNode* root) 
    {
        vector<vector<int>> res;
        if (NULL == root)
            return res;

        int i, left, right, nextlevel = 0, tobepush = 1;
        vector<int> vtmp;
        std::queue<TreeNode*> nodes;
        nodes.push(root);

        while (!nodes.empty())
        {
            TreeNode *nodetmp = nodes.front();
            vtmp.push_back(nodetmp->val);

            if (nodetmp->left) 
            {
                ++nextlevel;
                nodes.push(nodetmp->left);
            }
                
            if (nodetmp->right)
            {
                ++nextlevel;
                nodes.push(nodetmp->right);
            }
                
            nodes.pop();
            --tobepush;
            if (0 == tobepush)
            {
                res.push_back(vtmp);
                vtmp.clear();
                tobepush = nextlevel;
                nextlevel = 0;
            }
        }

        for (i = 1; i < res.size(); i += 2)
        {
            left = 0;right = res[i].size() - 1;
            while (left < right)
            {
                swap(res[i][left], res[i][right]);
                ++left;--right;
            }
        }
        return res;
    }

private:
    void swap(int& a, int& b)
    {
        int tmp = a;a = b;b = tmp;
    }
};

 

14.判断二叉树是否对称

class Solution {
public:
    bool isSymmetrical(TreeNode* pRoot)
    {
        if (NULL == pRoot)
            return true;
        else return judgeSymmetrical(pRoot->left, pRoot->right);
    }

private:
    bool judgeSymmetrical(TreeNode* left, TreeNode* right)
    {
        if (NULL == left&&NULL == right)
            return true;

        if (NULL == left || NULL == right)
            return false;

        if (left->val != right->val)
            return false; //注意此处不能判断相等返回true,因为下面还要进行判断

        return judgeSymmetrical(left->left, right->right)
            && judgeSymmetrical(left->right, right->left);
    }
};

很完美的思路,通过前序序列进行判断。

 

15.二叉树的序列化和反序列化

class Solution {
public:
    char* Serialize(TreeNode *root) 
    {
        string str;
        Serialize(root, str);

        int i,len = str.length();
        char *res = new char[len + 1];
        for (i = 0; i < len; i++)
            res[i] = str[i];
        res[i] = '\0';
        return res;
    }

    TreeNode* Deserialize(char *str) 
    {
        if (NULL == str || *str == '\0')
            return NULL;

        int left = 0;
        
        string numstr(str);
        
        TreeNode* head = Deserialize(numstr, left);
        return head;
    }

private:

    void Serialize(TreeNode *root, string& str)
    {
        if (NULL == root)
        {
            str += "#,"; return;
        }
        else
        {
            ostringstream ost;
            ost << root->val;
            str += ost.str() + ',';
        }

        Serialize(root->left, str);
        Serialize(root->right, str);
    }

    bool readstr(string& str,int& left, int& num)
    {
        if (str[left] == '#')
        {
            left += 2; //退后至下一个数字
            return false;
        }
        else
        {
            string tmp;
            while (str[left] != ',' && str[left] != '\0')
            {
                tmp += str[left++];
            }
            ++left;
            num = atoi(tmp.c_str());
            return true;
        }
    }

    TreeNode* Deserialize(string& numstr,int& left)
    {
        int num;
        if (readstr(numstr, left, num))
        {
            TreeNode* root = new TreeNode(num);
            
            root->left = Deserialize(numstr, left);
            root->right = Deserialize(numstr, left);
            return root;
        }
        return NULL;
    }
};

 

16.二叉搜索树的第K个节点

class Solution {
public:
    TreeNode* KthNode(TreeNode* pRoot, unsigned int k)
    {
        if (NULL == pRoot || k == 0)
            return NULL;

        return KthTreeNode(pRoot, k);
    }

private:
    TreeNode* KthTreeNode(TreeNode* root, unsigned int& k)
    {
        TreeNode* target = NULL;

        if (root->left != NULL)
            target = KthTreeNode(root->left, k);

        if (NULL == target)
        {
            if (k == 1)
                target = root;
            --k;
        }

        if (NULL == target&&root->right != NULL)
            target = KthTreeNode(root->right, k);

        return target;
    }
};

根据中序遍历的方式实现寻找。

posted @ 2015-08-18 13:58  从此寂静无声  阅读(259)  评论(0编辑  收藏  举报