关于剑指Offer的习题最优解

关于剑指Offer的习题最优解

问题与解释

  1. 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
/*
对于二位数组的长度获取,熟知size()用法。
因为是递增序列,对于有序序列可以使用二分查找。
如果使用循环遍历,在找到该值的之后,需要立马返回,节省性能。
注意,也许分为方阵和非方阵情况。
*/
//基本解,循环遍历
class Solution {
public:
    bool Find(int target, vector<vector<int> > array) {
        int row = array.size();
        int col = array[0].size();
        
        for (int i = 0; i < row; ++i) {
            for (int j = 0; j < col; ++j) {
                if (target == array[i][j])
                    return true;
            }
        }
        return false;
    }
};
//对角线法,通过对二维数组的有序规律,这个数的下方肯定比它大,这个数的左方肯定比它小,就有左下到右上的说法。
class Solution {
public:
    bool Find(int target, vector<vector<int> > array) {
            // array是二维数组,这里没做判空操作
            int rows = array.size();
            int cols = array[0].size();
            int i=rows-1,j=0;//左下角元素坐标
            while(i>=0 && j<cols){//使其不超出数组范围
                if(target<array[i][j])
                   i--;//查找的元素较少,往上找
                else if(target>array[i][j])
                   j++;//查找元素较大,往右找
                else
                   return true;//找到
            }
            return false;
    }
};


//二分法:对第一列的数进行二分查找,再到找到的行进行二分查找。

请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。

/*把空格替换之后增加了两个字符,所以后续用字符添加为了节省空间,如果是从头开始移动,会产生冲突。
*/class Solution {
public:
    void replaceSpace(char *str,int length) {
            int count = 0;
            for (int i=0; i<length; i++) {
                if(str[i] == ' ')
                	count++;
             }
             for (int i = length-1; i >= 0; i--) {
                if (str[i] != ' '){
                      str[i+2*count]=str[i];
                 } else {
                        count--;
                        str[i+2*count]='%';
                        str[i+2*count+1]='2';
                        str[i+2*count+2]='0';
                 } 
            }
      }
};
/*熟练使用C++特性*/
class Solution {
public:
    void replaceSpace(char *str,int length) {
        string s(str);
         int i=0;
         while((i = s.find(' ',i)) > -1){
              s.erase(i, 1);
              s.insert(i,"%20");
          }
          auto ret = s.c_str();
          strcpy(str, ret);
      }
};

输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。

class Solution {
public:
    vector<int> printListFromTailToHead(struct ListNode* head) {
            vector<int> v;
             while(head != NULL){
             v.insert(v.begin(),head->val);//头插法 
             head = head->next;
             }                
             return v;
     }
 };

class Solution {
public:
    vector<int> printListFromTailToHead(struct ListNode* head) {        
    vector<int> tmp;        
    ListNode *pHead = head;        
    while(pHead != NULL){            
	    tmp.push_back(pHead->val);            
	    pHead = pHead->next;        
    }        
    vector<int> result(tmp.rbegin(),tmp.rend());//反序输出        
    return result;    
    }
};


/*    先递归展开,在后续收缩栈时,推入VECTOR的节点是逆序,函数调用也是一个栈。*/
class Solution {
public:
    vector<int> printListFromTailToHead(struct ListNode* head) {
            if(!head)            
            return vec;        
            printListFromTailToHead(head->next);        
            vec.push_back(head->val);       
            return vec;    
            }
private:
	vector<int> vec;
};

class Solution {
public:
    vector<int> printListFromTailToHead(struct ListNode* head) {
            stack<int> a;        
            vector<int> b;        
            while(!head){            
	            a.push(head->val);            
	            head=head->next;        
            }        
            while(!a.empty()){            
	            b.push_back(a.top());            
	            a.pop();        
            }        
            	return b;    
            }
};

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

/* 
递归思想,每次将左右两颗子树当成新的子树进行处理,中序的左右子树索引很好找,前序的开始结束索引通过计算中序中左右子树的大小来计算,然后递归求解,直到startPre>endPre||startIn>endIn说明子树整理完到。方法每次返回左子树活右子树的根节点
 */
class Solution {
public:
    TreeNode* reConstructBinaryTree(vector<int> pre, vector<int> vin) {
            TreeNode* root = reConstructBinaryT(pre, 0, pre.size()-1,                                            vin, 0, vin.size()-1);
                    return root;   
              }
private:
    TreeNode reConstructBinaryT(vector<int> &pre, int beginPre, int endPre,                                vector<int> &vin, int beginvin, int endvin) {
            if (beginPre > endPre || beginVin > endVin)            
		return NULL;        
	    TreeNode* root = new TreeNode(pre[beginPre])
            for (int i = beginvin; i<=endvin; ++i) {            
            if (vin[i] == pre[beginPre]) {                
            root->left = reConstructBinaryTree(pre, beginPre+1, beginPre+i-beginvin,                                                   vin, beginvin, i-1);                
            root->right = reConstructBinaryTree(pre, i-beginvin+beginPre+1, endPre,                                                    vin, i+1, endvin);                
            break;            
            }        
        }        
        return root;    
	}
};

用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型

class Solution{
public:
    void push(int node) {
            	stack1.push(node);
            }    
            int pop() {        //等待栈2出完后才能继续入栈不然,不然就会占据栈顶        				
	            if(stack2.empty()){             
		            while(!stack1.empty()){               
		            stack2.push(stack1.top());                
		            stack1.pop();            
		            }        
                    }        
	                int t = stack2.top();        
	                stack2.pop();       
	                return t;    
	     } 
private:
    stack<int> stack1;
    stack<int> stack2;
};

感想与展望

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值