剑指offer数学题

来源:互联网 发布:js插件如何编写 闭包 编辑:程序博客网 时间:2024/05/21 09:25

1.斐波那契数列

F(0)=1;
F(1)=1;
F(n)=F(n-1)+F(n-2);
青蛙跳题目,兔子生兔子题目。
递归的方法

2.跳跳台

一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
class Solution {public:    int jumpFloor(int number) {        int fn=0;        int f1=1;        int f2=2;        if(number<1)return 0;        if(number==1)return 1;        if(number==2)return f2;        int count=3;        fn=f1+f2;        while(count<number)            {               f1=f2;               f2=fn;               fn=f1+f2;               count++;        }        return fn;    }};
      变态跳跳台
一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

f(1) = 1

f(2) = f(2-1) + f(2-2)         //f(2-2) 表示2阶一次跳2阶的次数。

f(3) = f(3-1) + f(3-2) + f(3-3) 

...

f(n) = f(n-1) + f(n-2) + f(n-3) + ... + f(n-(n-1)) + f(n-n) 

    f(n-1) = f(0) + f(1)+f(2)+f(3) + ... + f((n-1)-1) = f(0) + f(1) + f(2) + f(3) + ... + f(n-2)

    f(n) = f(0) + f(1) + f(2) + f(3) + ... + f(n-2) + f(n-1) = f(n-1) + f(n-1)

    可以得出:

    f(n) = 2*f(n-1)  

    在n阶台阶,一次有1、2、...n阶的跳的方式时,总得跳法为:

              | 1       ,(n=0 ) 

    f(n) =     | 1       ,(n=1 )

              | 2*f(n-1),(n>=2)

class Solution {public:    int jumpFloorII(int number) {          if(number==1)              return 1;          else              {               return (2*jumpFloorII(number-1));          }    }};

3.二进制中1的个数

输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示
class Solution {public:     int  NumberOf1(int n) {         int count=0;         unsigned int flag=1;         while(flag)             {               if(n&flag)                   count++;             flag=flag<<1;         }         return count;     }};
      

4.数值的整数次方

给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。
    对于exponent为负数,先求其绝对值的次方,然后求倒数。但对0求倒数(即底数为0,指数为负数时),还有0的0次方,但需要指出已经考虑。
class Solution {         public:             bool isequal(double num1,double num2)               {                   if(num1-num2<0.0000001&&num1-num2>-0.0000001)               return true;             else               return false;           }          //计算正指数的整数次方       double PowerWithUnsignedExponent(double base,unsigned int exponent)          {              double result=1.0;              unsigned int i;              for(i=1;i<=exponent;++i)                result*=base;              return result;          }         //利用乘方性质计算整数次方        double PowerWithUnsignedExponent2(double base,unsigned int exponent)       {             if(exponent==0) return 1;             if(exponent==1) return base;                double result=PowerWithUnsignedExponent2(base,exponent>>1);              result*=result;              if((exponent&0x1)==1)//指数为奇数                result*=base;               return result;         }          bool g_InvalidInput=false;//使用全局变量处理错误        double Power(double base, int exponent) {    // g_InvalidInput=false;        if(isequal(base,0.0)&&exponent<0)          {               g_InvalidInput=true;              return 0.0;          }        unsigned int absExponent=(unsigned int) (exponent);//定义了正指数        if(exponent<0)        absExponent=(unsigned int) (-exponent);          double result=PowerWithUnsignedExponent2(base,absExponent);          if(exponent<0)        result=1.0/result;        return result;       }};

5. 替换空格

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

class Solution {public:void replaceSpace(char *str,int length) {         if(str==NULL||length<=0)             return;        int Oldlen=0;        int Nonlen=0;        int Totallen=0;        for(int i=0;str[i]!='\0';i++)         {               Oldlen++;            //length++;            if(str[i]==' ')                Nonlen++;                      }        Totallen=Oldlen+2*Nonlen;        if(Totallen<Oldlen)            return;        int j=Totallen;        for(int i=Oldlen;i>0;i--)            {               if(str[i]!=' ');                {                      str[j--]=str[i];                }               else{                     str[j--]='0';                     str[j--]='2';                     str[j--]='%';                   }            }        }};

6.数组中出现出现超过一半次数的数字

数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。


class Solution {public:    int MoreThanHalfNum_Solution(vector<int> numbers) {        int length=numbers.size();        if(length<=0)            return false;        int results=numbers[0];        int count=0;        //判断数组是否满足条件        int i;        if( i=0;i<length;++i)             {               if(numbers[i]==results)                   count++;            }        if(2*count<=length)            return false;        for( i=1;i<length;i++)            {              if(count==0)                  {                   results=numbers[i];                   count++;                                }              else if(numbers[i]==results)                  {                   count++;                 }              else                count--;          }        return results;       }};

7.最小的k个数

输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,
   
class Solution {public:    void Swap(int *a,int *b)      {      if(*a != *b)      {          *a = *a + *b;          *b = *a - *b;          *a = *a - *b;      }    }      //算法导论,快速分割算法   int Partition(int *A,int low,int high)     {       if(A==NULL || low<0 || high<0 || low>=high)          return -1;            int small = low-1;      int j;      for(j=low;j<high;j++)      {          if(A[j] <= A[high])          {              ++small;              if(j != small)                  Swap(&A[j],&A[small]);          }      }      ++small;      Swap(&A[small],&A[high]);      return small;     }       vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {        if(k<=0)            return false;        int start=0;        int end=k-1;        int index=Partition(input,k,start,end);        while(index!=k-1)            {            if(index>k-1)                {                  end=index-1;                  index=Partition(input,k,start,end);            }            else{                start=index-1;                index=Partition(input,k,start,end);            }        }        //r(int i=0;i<k;i++)                   }};

8.连续子数组最大和

HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。你会不会被他忽悠住?(子向量的长度至少是1)
class Solution {public:    int FindGreatestSumOfSubArray(vector<int> array) {         int length=array.size();         if(length<=0)             return 0;        int curSum=0;        int newSum=0x80000000;        for(int i=0;i<length;++i)            {
         //             if(curSum<=0)                 curSum=array[i];             else                 curSum+=array[i];            if(curSum>newSum)                newSum=curSum;        }        return newSum;    }};

9.从1到n整数中1出现的次数

求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数。

(1)遍历解法,从1到n遍历每一个数,每个数判断1的个数,判断1的个数采取不断模10取余的方法,对于数字n,它有logn位,那么时间复杂度为O(nlogn),当n很大时,需要大量的计算,运算效率不高。

 (2)如果我们能统计每个位上出现的次数,最后总次数就是把每个位上出现的次数加起来就可以了。例如输入数字21345,我们把数字分成两段,1~1345,1346~21345.先从高位计算1的个数,如果1出现在万位上,那么有10000~19999总共有10000种可能。需要注意的是如果最高位是1,譬如数字是11345,那么做高位的1只可能出现在10000~11345中,有1345+1中可能。接着我们再统计1出现在后四位中。我们把1346~21345再分成1346~11345和11346~21345两段。如果1出现在千位上,那么剩余三位可以取0~9中的任意数字,总共有10的3次方1000中可能。1出现在剩下的低位中情况完全类似,所以1出现在剩下的后四位中总共有4*1000*2 = 8000个。接着再统计1~1345中1出现的个数,由于1345只是我们开始的数字21345去掉了最高位,所以完全可以用递归的方法解决。递归的终止条件是只剩下一位数字。其复杂度为logn。

class Solution {public:    int NumberOf1Between1AndN_Solution(int n)    {        if(n<0)            return 0;      int count = 0;      for (int i = 1; i <= n; i *= 10)      {          int a = n / i,b = n % i;        //之所以补8,是因为当百位为0,则a/10==(a+8)/10,        //当百位>=2,补8会产生进位位,效果等同于(a/10+1)          count += (a + 8) / 10 * i + ((a % 10 == 1) ? b + 1 : 0);       }       return count;    }};

10.丑数

把只包含素因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。

class Solution {public:    int Min(int number1,int number2,int number3)        {                  int min =(number1<number2)?number1:number2;          min=(min<number3)?min:number3;          return min;    }    int GetUglyNumber_Solution(int index) {    //每一个丑数必然是由之前的某个丑数与2,3或5的乘积得到的,这样下一个丑数就用之前的丑数分别乘以2,3,5,找出这三这种最小的并且大于当前最大丑数的值,即为下一个要求的丑数。    if(index <= 0)          return 0;      int *UglyNums=new int[index];    UglyNums[0] = 1;      int CurrentIndex= 1;    //当前要求的丑数的下标索引      int *p2 = UglyNums;      int *p3 = UglyNums;      int *p5 = UglyNums;        //求每个丑数,并保存起来      while(CurrentIndex < index)      {          int min = Min(2*(*p2),3*(*p3),5*(*p5));          UglyNums[CurrentIndex] = min;                    //每次循环都从上次的p2,p3和p5的下一个位置开始          while(2*(*p2) <= UglyNums[CurrentIndex])              ++p2;          while(3*(*p3) <= UglyNums[CurrentIndex])              ++p3;          while(5*(*p5) <= UglyNums[CurrentIndex])              ++p5;            ++CurrentIndex;      }        int result = UglyNums[index-1];      return result;      }};






0 0