剑指offer刷题记录

1.二维数组中的查找

在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

解法1:有序数组想到二分查找,由于是二维数组,即进行多行的二分查找

    bool Find(int target, vector<vector<int> > array){
        if(array.size()==0){
            return false;
        }
        for(int i=0;i<array.size();i++){
            int low = 0,high = array[0].size()-1;
            int mid;
            while(low<=high){
                mid = (low + high)/2;
                if(array[i][mid]==target){
                    return true;
                }
                if(array[i][mid]<target){
                    low = mid + 1;
                }else{
                    high = mid -1;
                }
            }
        }
        
        return false;
    } 

解法2:找到一个分界点,考虑4个点:左上、左下、右上、右下。左上角数值最小,向右和向下都是比它大的数,没有区分度,同理右下角也是,因此只能选择左下角或者右上角。

从左下角开始,只要比当前小的值,往上移,比当前值大的,往右移。

从右上角开始,只要比当前值小的,往下移,比当前值大的,往左移。

bool Find(int target, vector<vector<int> > array) {
       //从[0,n-1]的位置开始查找
        //> i++
        //< j--
        if(array.size()==0){
            return false;
        }
        int height = array.size();
        int width = array[0].size();
        int i= 0,j=width-1;
        
        while(i>=0&&j<width&&i<height&&j>=0){
            if(array[i][j]==target){
                return true;
            }else if (array[i][j]>target){
                j--;
            }else{
                i++;
            }
        }
        
        return false;
    }

2.替换空格 卡

3.从尾到头打印链表

思路1:从头到尾-->从尾到头 联想到栈,使用栈来记录节点

vector<int> printListFromTailToHead(ListNode* head) {
         // 栈的特性
         stack<ListNode *> s;
         vector<int>res;
         if(head==NULL){
             return res;
         }
         ListNode *p = head;
         while(p!=NULL){
             s.push(p);
             p = p->next;
         }
         
         while(!s.empty()){
             int val = s.top()->val;
             res.push_back(val);
             s.pop();
         }
         
         return res;
     }

思路2:先将链表进行遍历,记录节点个数,然后再重新遍历链表,数组下标位置移动从尾到头

vector<int> printListFromTailToHead(ListNode* head) {
        // 先扫描一遍然后再填
        
        int length = 0;
        ListNode *p = head;
        while(p!=NULL){
            p = p->next;
            length++;
        }
        
        vector<int> res(length);
        int count = length-1;
        p=head;
        while(p!=NULL){
                int t = p->val;
                    p = p->next;
                    res[count--] = t;
                }
        
        return res;
            }

4.重建二叉树

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

 

TreeNode * bulid(vector<int> pre,int pre_begin,int pre_end,vector<int>post,int post_begin,int post_end)

递归左子树TreeNode * bulid(vector<int> pre,int pre_begin+1,int pre_begin+1+ left,vector<int>post,int post_begin,int post_begin+ left)

递归右子树TreeNode * bulid(vector<int> pre,int pos+1,int pre_end,vector<int>post,int pos+1,int post_end)

 

    TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
         TreeNode *s = recon(pre,vin,0,pre.size()-1,0,pre.size()-1);
         return s;
    }
    
     TreeNode* recon(vector<int> pre,vector<int> vin,int prel,int preh,int vinl,int vinh){
         
         if(vinl==vinh){
             TreeNode *s = new TreeNode (vin[vinl]);
             cout<<"con "<<endl;
             s->left = NULL;
             s->right = NULL;
             return s;
         }
         int r;
         for(int i=vinl;i<=vinh;i++){
             if(vin[i]==pre[prel]){
                 r = i;break;
             }
         }
         TreeNode *s = new TreeNode (vin[r]);
         s->left = NULL;
         s->right = NULL;
         
         if(r>vinl){
             //cout<<pre[prel+1]<<pre[prel+(r-vinl)]<<endl;
             s->left = recon(pre,vin,prel+1,prel+(r-vinl),vinl,r-1);
         }
         
         if(r<vinh){
              //cout<<pre[prel+(r-vinl)+1]<<pre[preh]<<endl;
             s->right = recon(pre,vin,prel+(r-vinl)+1,preh,r+1,vinh);
         }
         
            return s;
     }

5.用两个栈实现队列

思路:栈1用来进栈,栈2用来出栈

进栈时可以直接进栈1,出栈时先判断栈2是否为空,若不为空,则栈2栈顶元素出栈,若为空,则判断栈1是否为空,若栈1为空,则退出,若不为空,则将栈1元素进栈到栈2再进行出栈。

class Solution
{
public:
    void push(int node) {
        stack1.push(node);
    }

    int pop() {
        int res;
        if(stack2.empty()&&stack1.empty()){
            return -1;
        }
        if(!stack2.empty()){
            res = stack2.top();
            stack2.pop();
            return res;
        }
        
        while(!stack1.empty()){
            res = stack1.top();
            stack1.pop();
            stack2.push(res);
        }
            res = stack2.top();
            stack2.pop();
            return res;
        
    }

private:
    stack<int> stack1;
    stack<int> stack2;
};

6.旋转数组的最小数字

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值