【46-50】剑指offer

46.题目描述

每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此。HF作为牛客的资深元老,自然也准备了一些小游戏。其中,有个游戏是这样的:首先,让小朋友们围成一个大圈。然后,他随机指定一个数m,让编号为0的小朋友开始报数。每次喊到m-1的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续0...m-1报数....这样下去....直到剩下最后一个小朋友,可以不用表演,并且拿到牛客名贵的名侦探柯南典藏版(名额有限哦!!^_^)。请你试着想下,哪个小朋友会得到这份礼品呢?(注:小朋友的编号是从0n-1)

思路:1.采用循环链表的方式实现

      2.通过数学推导,得出递归公式,然后按照递归公式编写

      具体实现见代码:

#include <iostream>

#include <list>

using namespace std;

 

class Solution {

public:

       //链表实现

   int LastRemaining_Solution(unsigned int n, unsigned int m)

    {

              //检查输入是否合法

              if(n< 1 || m < 1)

                     return-1;

 

       list<int> lList(n);

              list<int>::iteratorite = lList.begin();

              //初始化链表

              inti = 0;

              for(;ite != lList.end(); ite++)

                     *ite= i++;

 

              //循环删除链表

              ite= lList.begin();

 

              while(lList.size()> 1)

              {

                     for(i= 1; i < m; i++)

                     {

                            ite++;

                            if(ite== lList.end())

                                   ite= lList.begin();

                     }

 

                     list<int>::iteratoriteTemp = ++ite;

                     if(iteTemp== lList.end())

                            iteTemp= lList.begin();

 

                     lList.erase(--ite);

                     ite= iteTemp;

              }

              returnlList.front();

    }

 

       //数学推导实现

       intLastRemaining_Solution1(unsigned int n, unsigned int m)

    {

              if(n<1|| m < 1)

                     return-1;

 

              intlast = 0;

              for(inti = 2; i <= n; i++)

                     last= (last + m)%i;

              returnlast;

       }

};

 

int main()

{

       Solutions;

       cout<<s.LastRemaining_Solution(10,30)<<endl;

       cout<<s.LastRemaining_Solution1(10,30)<<endl;

      

       return0;

}

 

47.题目描述

1+2+3+...+n,要求不能使用乘除法、forwhileifelseswitchcase等关键字及条件判断语句(A?B:C)。

#include<iostream>

using namespace std;

 

class Solution {

private:

       staticint nN;

       staticlong int nSum;

public:

       //构造函数中实现自加

       Solution()

       {

              nN++;

              nSum+= nN;

       }

       //重置nN和nSum

       staticvoid Reset()

       {

              nN= 0;

              nSum= 0;

       }

       //返回求和结果

       staticlong int GetSum()

       {

              returnnSum;

       }

       //求前n项和

   int Sum_Solution(int n)

       {

              Solution::Reset();

 

              Solution*temp = new Solution[n];

              delete[] temp;

              temp= NULL;

                    

              returnSolution::GetSum();

    }

};

 

int Solution::nN = 0;

long int Solution::nSum = 0;

 

int main()

{

       Solutions;

       cout<<s.Sum_Solution(100)<<endl;

      

       return0;

}

 

48.题目描述

写一个函数,求两个整数之和,要求在函数体内不得使用+-*/四则运算符号。

 

#include <iostream>

using namespace std;

 

class Solution {

public:

   int Add(int num1, int num2)

    {

              intnSum, nCarry;

              do

              {

                     nSum= num1 ^ num2;

                     nCarry= (num1 & num2)<<1;

 

                     num1= nSum;

                     num2= nCarry;

              }while(num2 != 0);

 

              returnnum1;

    }

};

 

int main()

{

       Solutions;

       cout<<s.Add(100,55)<<endl;

      

       return0;

}

 

49.题目描述

将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数。

    注意:仔细考略一些输入不合法情况的处理。

#include <iostream>

using namespace std;

 

enum IsValid{VALID = 0, INVALID};

IsValid flagError = VALID;

 

class Solution {

public:

   int StrToInt(string str)

       {

              //处理字符串"",输入不合法"!*"的情况,第一个字符为'+'或者为'-'表示输入为正负数

              if(str.size()==0)

              {

                     flagError= INVALID;

                     return0;

              }

 

              intflag = 1; //1 表示正数,-1表示负数

              flagError= VALID;

              char*pStr = &str[0];

             

              for(inti = 0; i < str.size(); i++)

              {

                     if(i== 0)

                     {

                            if(str[i]== '+')

                            {

                                   pStr++;

                                   flag= 1;

                                   continue;

                            }

                            if(str[i]== '-')

                            {

                                   pStr++;

                                   flag= -1;

                                   continue;

                            }

                     }

                     if(str[i]> '9' || str[i] < '0')

                     {

                            flagError= INVALID;

                            return0;

                     }

              }

             

              returnStrToInt(pStr, flag);

    }

      

       intStrToInt(char *pStr, int NePoFlag)

       {

              intnumber = 0;

              while(*pStr!= '\0')

              {

                     number= number*10 + NePoFlag*(*pStr-'0');

                     pStr++;

              }

 

              returnnumber;

       }

};

 

int main()

{

       Solutions;

       cout<<s.StrToInt("+1232")<<endl;

       cout<<s.StrToInt("-132")<<endl;

       cout<<s.StrToInt("+1da2")<<endl;

       cout<<s.StrToInt("")<<endl;

       cout<<s.StrToInt("1232")<<endl;

 

       return0;

}

 

50.题目描述

在一个长度为n的数组里的所有数字都在0n-1的范围内。数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是重复的数字2或者3

思路:因为数组元素是在0-n-1范围内,那么若排序后i位置的值为i,那么数组不存在重复的数字,否则存在重复的数字。

 

#include <iostream>

using namespace std;

 

class Solution {

public:

   // Parameters:

   //        numbers:     an array of integers

   //        length:      the length of array numbers

   //        duplication: (Output)the duplicated number in the array number

   // Return value:       true if theinput is valid, and there are some duplications in the array number

   //                     otherwisefalse

   bool duplicate(int numbers[], int length, int* duplication)

       {

              //如果数组为NULL,则返回

              if(numbers== NULL || length < 1)

                     returnfalse;

      

              for(inti = 0; i < length; i++)

              {

                     while(numbers[i]!= i)

                     {

                            if(numbers[i]== numbers[numbers[i]])

                            {

                                   *duplication= numbers[i];

                                   returntrue;

                            }

                            inttemp = numbers[i];

                           

                            numbers[i]= numbers[numbers[i]];

                            numbers[temp]= temp;

                     }

              }

       return false;

    }

};

 

int main()

{

       intarray[] = {2,3,1,0,2,5,3};

       Solutions;

       intdup;

       if(s.duplicate(array,7, &dup))

       {

              cout<<"存在重复的数字"<<endl;

              cout<<dup<<endl;

       }

       else

              cout<<"不存在重复的数字"<<endl;

 

       return0;

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值