《剑指offer》Q01-12 (牛客10.11)

T1 二维部分有序数组查找 ☆

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

由于矩阵部分有序,向上数字递减,向右数字递增:

  1. 目标数字只会出现在行首小于该数的行中
  2. 遍历行i ,若列j 对应的元素大于目标,那么在前 i-1 行,目标只会出现在 j列及以后。

因此,可以从左下角开始查找。目标比左下角数字小时,上移;当要目标比左下角数字大时,右移。
搜索的路线是阶梯状,复杂度为O(行数+列数)。

class Solution {
public:
    bool Find(int target, vector<vector<int> > array) {
        int nrows = array.size();
        int ncols = array[0].size();
         
        int i = nrows - 1, j = 0;
         
        while(i >= 0 && j < ncols){
            if(array[i][j] == target) return true;
            else if(array[i][j]< target ){
                j++;
            }else i--;
        }
         
        return false;
    }
};

WA警告:

之前的错误代码版本如下,由于判断条件中的 && 写成 , 造成段错误(数组越界访问):

class Solution {
public:
    bool Find(int target, vector<vector<int> > array) {
        int nrows = array.size();
        int ncols = array[0].size();
        if( ncols == 0 || nrows == 0) return false;
        for(int i = nrows - 1, j = 0; i >= 0, j < ncols; i--){
            if( array[i][j] == target )
                return true;
            if( array[i][j] < target){
                i++;
                j++;
            }
        }
          
        return false;
    }
};

T2 字符串字符不等长替换 - 从后往前

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

实现统计好空格数目从后往前写。问题是 str 所指的空间会内存泄露吧?
注意补上 ''(应该不会有憨憨如我补了一个' '...

T3 返回链表的反序 vector

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

递归或者对正序 vector reverse。

class Solution {
public:
    vector<int> printListFromTailToHead(ListNode* head) {
        vector<int> rst;
        if(head == NULL)return rst;
        rst = printListFromTailToHead(head->next);
        rst.emplace_back(head->val);
        return rst;
    }
};

//----------------------vv---------------------------------
class Solution {
public:
    vector<int> printListFromTailToHead(ListNode* head) {
        vector<int> rst;
         
        ListNode* pNode = head;
        while(pNode!=NULL){
            rst.emplace_back(pNode->val);
            pNode=pNode->next;
        }
         
        reverse(rst.begin(),rst.end());
        return rst;
    }
};

T4 重建二叉树

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

递归建树。注意递归出口,当有 0 或一个节点时直接返回。

/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
        if(pre.size()==0)
            return NULL;
        if(pre.size()==1)
            return new TreeNode(pre[0]);
        TreeNode* root = new TreeNode(pre[0]);
        int lenl =0, lenr = 0,len = vin.size();
        while(lenl<len && vin[lenl]!= pre[0])
            lenl++;
        vector<int> npre,nvin;
        
        npre = vector<int>(pre.begin()+1,pre.begin()+1+lenl);
        nvin = vector<int>(vin.begin(),vin.begin()+lenl);
        root->left = reConstructBinaryTree(npre,nvin);
        
        npre = vector<int>(pre.begin()+1+lenl,pre.end());
        nvin = vector<int>(vin.begin()+lenl+1,vin.end());
        root->right = reConstructBinaryTree(npre,nvin);
        
        return root;
    }
};

T5 两个栈模拟队列

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

栈1接收入队列元素,栈2存储出队列元素,当栈2空时,把栈1元素倒到栈2中。

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

    int pop() {
        if(stack2.size()==0){
            while(!stack1.empty()){
                int x=stack1.top();
                stack1.pop();
                stack2.push(x);
            }
        }
        int x=stack2.top();
        stack2.pop();
        return x;
    }

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

T6 旋转数组中的最小元素 - 二分或暴力 ☆

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

由于旋转后,数组前半段非减,后半段非减,所以从后往前遍历,转折点一定是最小元素。如果没有转折点,那么所有元素都相等。
​ . .··
​ . ·``

但是这个转折点可以试着二分。由于转折处的右侧是最小元素,所以选择尽量让区间右端点落在最小元素上。那么:

  1. array[mid] > array[high]
    出现这种情况的array类似[3,4,5,6,0,1,2],此时最小数字一定在mid的右边。
    low = mid + 1
  2. array[mid] == array[high]:
    出现这种情况的array类似 [1,0,1,1,1] 或者[1,1,1,0,1],此时最小数字不好判断在mid左边还是右边,这时只好一步步缩小区间。
    high = high - 1
  3. array[mid] < array[high]:
    出现这种情况的array类似[2,2,3,4,5,6,6],此时最小数字一定就是array[mid]或者在mid的左边。因为右边必然都是递增的。
    high = mid

注意,考虑最后区间长为2或为3 的情况,上述的收敛方式都会使得 low 和 high 最终都指向最小元素。

class Solution {
public:
    int minNumberInRotateArray(vector<int> rotateArray) {
        if(rotateArray.size()==0)
            return 0;
        int lo =0, hi = rotateArray.size()-1,mid;
         
        while(lo< hi){
            mid = lo+((hi-lo)>>1);
            if(rotateArray[mid]>rotateArray[hi])
                lo=mid+1;
            else if (rotateArray[mid] == rotateArray[hi])
                hi-=1;
            else hi=mid;
        }
        return rotateArray[hi];
    }
};

T7 - 10 斐波那契数列 - 递推递归 - 两变量写法

T7:大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0)。 n<=39。

class Solution {
public:
    int Fibonacci(int n) {
        if(n==0) return 0;
        if(n==1) return 1;
        if(n==2) return 1;
        return Fibonacci(n-1)+Fibonacci(n-2);
    }
};

T8:一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。

// 两变量
class Solution {
public:
    int jumpFloor(int number) {
        if(number==0)return 1;
        if(number==1)return 1;
        if(number==2)return 2;
        int f=1,g=2;
        number-=2;
        while(number--){
            g=f+g;
            f=g-f;
        }
        return g;
    }
};

T9:一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

// dp
class Solution {
public:
    int jumpFloorII(const int number) {
        int** dp=new int*[number+10];
        for(int i=0;i<number+10;i++){
            dp[i]=new int[number+10];
        }
        
        memset(dp,0,sizeof dp);
        
        for(int i=1;i<=number;i++){
            dp[1][i]=1;
        }
        // dp[i][j] 用i步跳上台阶j
        for(int i=2;i<=number;i++){
            for(int j=i;j<=number;j++){
                for(int k=i-1;k<j;k++){
                    dp[i][j]+=dp[i-1][k];
                }
            }
        }
        
        int ans=0;
        for(int i=1;i<=number;i++){
            ans+=dp[i][number];  
        }
        return ans;// 返回的变量打错,不可原谅,,
    }
};

T10:我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?

类似于前面几题。

class Solution {
public:
    int rectCover(int number) {
        if(number==0)    return 0;
        if(number==1)    return 1;
        if(number==2)    return 2;
        int f=1,g=2;
        number-=2;
        while(number--){
            g=f+g;
            f=g-f;
        }
        return g;
    }
};

T11 二进制中 1 的个数

输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。

注意对于负数,右移一位会补 1 而非补零。

// 1. 去掉符号位 1
class Solution {
public:
     int  NumberOf1(int n) {
         int cnt=0;
         if(n<0) {
             n &=0x7fffffff;
             cnt++;
         }
        
         while(n){
             cnt+=(n&1);
             n>>=1;
         }
         return cnt;
     }
};

// 2. 转为 unsigned int
class Solution {
public:
     int  NumberOf1(int n) {
         unsigned int nn=n;
         int cnt=0;

         while(nn){
             cnt+=(nn&1);
             nn>>=1;
         }
         return cnt;
     }
};

// 3. 每次 n&(n-1) 将从右边起的第一个 1 变为 0
public class Solution {
    public int NumberOf1(int n) {
        int count = 0;
        while(n!= 0){
            count++;
            n = n & (n - 1);
         }
        return count;
    }
} 

T12 数值的整数次方 - 缜密 - 基数可能为负数

给定一个double类型的浮点数 base 和 int 类型的整数exponent。求base的exponent次方。 保证base和exponent不同时为0

class Solution {
public:
    double Power(double base, int exponent) {
        double ans=1;
        bool neg= false;
        
        else if(exponent<0){
            neg=true;
            exponent=-exponent;
        }
        for( ; exponent; base*=base,exponent/=2){
            if(exponent&1){
                ans*=base;
            }
        }
        return neg?1/ans:ans;
    }
};
原文地址:https://www.cnblogs.com/weseewe/p/11675019.html