zoukankan      html  css  js  c++  java
  • 剑指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!=''&&isdigit(**str))
                ++(*str);
        }
        
        bool isexpand(char** str){
            if(**str!='E'&&**str!='e')
                return false;
            
            ++(*str);
            if(**str=='+'||**str=='-')
                ++(*str);
            
            if(**str=='')
                return false;
            
            scandigits(str);
            return (**str=='')?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=='') return false;
            
            scandigits(&str);
            if(*str!=''){
                //针对小数进行处理
                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=='');
        }
    
    };
    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==''&&*pattern=='')
                return true;
             
            if(*str!=''&&*pattern=='')
                return false;
             
            if(*(pattern+1)=='*'){
                if(*pattern==*str||(*pattern=='.'&&*str!=''))
                    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!=''))
                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] = '';
            return res;
        }
    
        TreeNode* Deserialize(char *str) 
        {
            if (NULL == str || *str == '')
                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] != '')
                {
                    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;
        }
    };

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

  • 相关阅读:
    flock对文件锁定读写操作的问题 简单
    hdu 2899 Strange Fuction(二分)
    hdu 2199 Can you solve this equation? (二分)
    poj 3080 Blue Jeans (KMP)
    poj 2823 Sliding Window (单调队列)
    poj 2001 Shortest Prefixes (trie)
    poj 2503 Babelfish (trie)
    poj 1936 All in All
    hdu 3507 Print Article (DP, Monotone Queue)
    fzu 1894 志愿者选拔 (单调队列)
  • 原文地址:https://www.cnblogs.com/jason1990/p/4739232.html
Copyright © 2011-2022 走看看