剑指offer(六)其他

转载 2018年04月16日 18:00:15

面试题9:斐波那契数列

题目:大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项。n<=39
举一反三:青蛙跳台阶;小矩形覆盖大矩形。

class Solution {
public:
    int Fibonacci(int n) {
        int num[n];
        num[0] = 0;
        num[1] = 1;
        for(int i=2; i<=n; i++){
            num[i] = num[i-2]+num[i-1];
        }
        return num[n];
    }
};

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

class Solution {
public:
    int jumpFloor(int number) {
        int num[number];
        num[0] = 1;
        num[1] = 1;
        for(int i=2; i<=number; i++){
            num[i] = num[i-1]+num[i-2];
        }
        return num[number];
    }
};

题目:一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
解题思路:得出规律f(n)=2的(n-1)次方。

class Solution {
public:
    int jumpFloorII(int number) {
        int num[number];
        num[1] = 1;
        for(int i=2; i<=number; i++){
            num[i] = 2*num[i-1];
        }
        return num[number];
    }
};

题目:我们可以用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 sum, num1=1, num2 = 2;
        for(int i=3;i<=number;i++){
            sum = num1+num2;
            num1 = num2;
            num2 = sum;
        }
        return sum;
    }
};

面试题10:二进制中1的个数

题目:输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
解题思路:第一种方法是该数和1相与后右移一位,但是无法解决负数问题;第二种方法是该数和1相与后,1左移一位,循环次数就是该数的二进制位数;第三种方法是该数和(该数减1)相与,那么该数的二进制中最右边的1变成0其他位数不变,循环次数就是该数二进制中1的个数,此法最佳。
举一反三:用一条语句判断一个整数是不是2的整数次方(如果是的话,它的二进制表示有且只有1位是1)。计算需要改变m的二进制数中的多少位才能得到n(先异或,再统计异或结果中1 的位数)。

class Solution {
public:
     int  NumberOf1(int n) {
         int count = 0;
         while(n){
             count++;
             n = (n-1) & n;
         }
         return count;
     }
};

面试题11:数值的整数次方

题目:给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。
解题思路:两个情况需要考虑到,一是base为0,exponent<0时,返回0,用全局变量g_InvalidInput提示;二是base非0,exponent<0时,对正数时的它求导数即可。

class Solution {
public:
    bool g_InvalidInput = false;
    double Power(double base, int exponent) {
        if(equal(base,0.0) && exponent<0){
            g_InvalidInput = true;
            return 0.0;
        }
        int absExponent = exponent;
        if(exponent<0)
            absExponent = -exponent;
        double res = powerWithUnsignedExponent(base, absExponent);
        if(exponent<0)
            res = 1.0/res;
        return res;
    }
    bool equal(double num1, double num2){
        if((num1 - num2 < 0.0000001) && (num1 - num2 > -0.0000001))
            return true;
        else
            return false;
    }
    double powerWithUnsignedExponent(double base, int exponent){
        if(exponent == 0)
            return 1;
        if(exponent == 1)
            return base;
        double result = powerWithUnsignedExponent(base, exponent>>1);
        result *= result;
        if(exponent & 0x1 == 1)
            result *= base;
        return result;
    }
};

面试题20:顺时针打印矩阵

题目:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.
解题思路:要注意中间maxCol和minCol、maxRow和minRow的大小判断,以防剩下一列和一行的情况。

class Solution {
public:
    vector<int> printMatrix(vector<vector<int> > matrix) {
        vector<int> result;
        int rows = matrix.size();
        int columns = matrix[0].size();
        int minRow = 0, maxRow = rows-1, minCol = 0, maxCol = columns-1;
        int curRow, curCol;
        while(minRow<=maxRow && minCol<=maxCol){
            for(curRow = minRow, curCol = minCol; curCol <= maxCol; curCol++){
                result.push_back(matrix[curRow][curCol]);
            }
            minRow++;
            for(curRow = minRow, curCol = maxCol; curRow <= maxRow; curRow++){
                result.push_back(matrix[curRow][curCol]);
            }
            maxCol--;
            if(maxCol < minCol || maxRow < minRow)
                break;
            for(curRow = maxRow, curCol = maxCol; curCol >= minCol; curCol--){
                result.push_back(matrix[curRow][curCol]);
            }
            maxRow--;
            for(curRow = maxRow, curCol = minCol; curRow >= minRow; curRow--){
                result.push_back(matrix[curRow][curCol]);
            }
            minCol++;
        }
        return result;
    }
};

面试题32:从1到n整数中1出现的次数

题目:输入一个整数n,求从1到n这n个整数的十进制中1出现的次数。
解题思路:把数分成两部分,对前部分递归计算,对后部分直接计算。

class Solution {
public:
    int NumberOf1Between1AndN_Solution(int n)
    {
        if(n <= 0)
            return 0;
        char str[50];
        sprintf(str,"%d",n);
        return numberOf1(str);
    }
    int numberOf1(const char* str){
        if(!str || *str=='\0' || *str<'0' || *str>'9')
            return 0;
        //假设str是“21345”
        int firstNum = *str - '0';  //firstNum=2
        int length = strlen(str);
        if(length==1 && firstNum==0) //终止条件是length=1
            return 0;
        if(length==1 && firstNum>0)
            return 1;
        int firstDigit = 0;
        //firstDigit保存1345-21345之间最高为1的数的数目
        if(firstNum > 1)
            firstDigit = powerBase10(length-1);
        else if(firstNum == 1)
            firstDigit = atoi(str+1)+1;
        //OtherDigits保存1345-21345之间后4位出现1的数的数目:2*4*1000
        int OtherDigits = firstNum * (length-1) * powerBase10(length-2);
        //recursive保存1-1345之间出现1的数目,递归
        int recursive = numberOf1(str+1);
        //三数相加
        return firstDigit+OtherDigits+recursive;
    }
    int powerBase10(int n){
        int result = 1;
        while(n--)
            result *= 10;
        return result;
    }
};

面试题34:丑数

题目:把只包含因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
解题思路:寻找规律以避免对非丑数的计算。新的丑数来自于旧的丑数乘以2/3/5,所以用一个辅助数组保存已经计算出的丑数,将其乘以2/3/5,分别求出比已有最大丑数M大但又最接近M的数:M2/M3/M5,再求其中最小的一个,就是下一个丑数。这个方法以空间消耗换取时间效率的提升。

class Solution {
public:
    int GetUglyNumber_Solution(int index) {
        if(index<=0)
            return 0;
        int uglyNumbers[index];
        uglyNumbers[0] = 1;
        int *M2 = uglyNumbers;
        int *M3 = uglyNumbers;
        int *M5 = uglyNumbers;
        int uglyIndex = 1;
        while(uglyIndex < index){
            int minNum = Min(*M2 * 2, *M3 * 3, *M5 * 5);
            uglyNumbers[uglyIndex++] = minNum;
            while(*M2 * 2 <= minNum)
                M2++;
            while(*M3 * 3 <= minNum)
                M3++;
            while(*M5 * 5 <= minNum)
                M5++;
        }
        int result = uglyNumbers[uglyIndex-1];
        return result;
    }
    int Min(int a,int b,int c){
        int min = (a < b) ? a : b;
        return (min < c) ? min : c;
    }
};

面试题41:和为S的连续正数序列

题目:输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序
解题思路:两个指针从头出发,若小于sum则right向前走一步,若大于sum则left向前走一步,若等于sum则添加到vector中接着让right向前走一步,停止条件是left走到(sum+1)/2.

class Solution {
public:
    vector<vector<int> > FindContinuousSequence(int sum) {
        vector<vector<int>> result;
        if(sum < 3)
            return result;
        int left = 1;
        int right = 2;
        int curSum = left + right;
        while(left < (sum+1)/2){
            if(curSum < sum){
                right++;
                curSum += right;
            }else if(curSum > sum){
                curSum -= left;
                left++;
            }else{
                vector<int> tmp;
                for(int i=left;i<=right;i++){
                    tmp.push_back(i);
                }
                result.push_back(tmp);
                right++;
                curSum += right;
            }
        }
        return result;
    }
};

题目:输入一个递增排序的数组和一个数字S,在数组中查找两个数,是的他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。对应每个测试案例,输出两个数,小的先输出。
解题思路:两个指针一头一尾出发。

class Solution {
public:
    vector<int> FindNumbersWithSum(vector<int> array,int sum) {
        vector<int> result;
        int len = array.size();
        if(len > 1){
            int left = 0;
            int right = len-1;
            while(left < right){
                int curSum = array[left] + array[right];
                if(curSum == sum){
                    result.push_back(array[left]);
                    result.push_back(array[right]);
                    break;
                }else if(curSum > sum){
                    right--;
                }else{
                    left++;
                }
            }
        }
        return result;
    }
};
收藏助手
不良信息举报
您举报文章:剑指offer(六)其他
举报原因:
原因补充:

(最多只允许输入30个字)