孩子们的游戏(圆圈中最后剩下的数)
每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此。HF作为牛客的资深元老,自然也准备了一些小游戏。其中,有个游戏是这样的:首先,让小朋友们围成一个大圈。然后,他随机指定一个数m,让编号为0的小朋友开始报数。每次喊到m-1的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续0…m-1报数…这样下去…直到剩下最后一个小朋友,可以不用表演,并且拿到牛客名贵的“名侦探柯南”典藏版(名额有限哦!!_)。请你试着想下,哪个小朋友会得到这份礼品呢?(注:小朋友的编号是从0到n-1)
有名的约瑟夫环问题:我们明确知道了n个元素,每逢第m个删除。
环形链表
可以使用list进行实现,当迭代器走到list.end()时候,让迭代器再指向list.begin(),构成环状。
class Solution {
public:
int LastRemaining_Solution(int n, int m)
{
if(n<1||m<1)
return -1;
list<int> cirlist;
for(size_t i=0;i<n;i++)
cirlist.push_back(i);
list<int>::iterator cur=cirlist.begin();
while(cirlist.size()>1)
{
for(size_t i=0;i<m-1;i++)
{
cur++;
if(cur==cirlist.end())
cur=cirlist.begin();
}
//此时cur指向m-1号同学
list<int>::iterator next=++cur;
if(next==cirlist.end())
next=cirlist.begin();
--cur;
cirlist.erase(cur);
cur=next;
}
return *cur;
}
};
求1+2+3+…+n
求1+2+3+…+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。
利用构造函数
class Solution {
class Sum
{
public:
Sum()
{
_sum+=_i;
++_i;
}
static int& GetSum()
{
return _sum;
}
static int _sum;
static int _i;
};
public:
int Sum_Solution(int n) {
Sum::_sum=0;
Sum::_i=1;
new Sum[n];
return Sum::GetSum();
}
};
int Solution::Sum::_sum=0;
int Solution::Sum::_i=1;
利用虚函数
这里采用虚函数实现了递归的效果,虽然不能进行if、else判断,我们可以用
!
!
n
!!n
!!n来确定n是否为0,如果n是0,
!
!
n
=
f
a
l
s
e
!!n=false
!!n=false,如果n不是0,
!
!
n
=
t
r
u
e
!!n=true
!!n=true,从而实现了判断。
class A;
A* AA[2];
class A{
public:
virtual size_t Sum(size_t n)
{
return 0;
}
};
class B :public A
{
virtual size_t Sum(size_t n)
{
return AA[!!n]->Sum(n - 1) + n;
}
};
class Solution {
public:
int Sum_Solution(int n) {
A a;
B b;
AA[0]=&a;
AA[1]=&b;
int ret=AA[1]->Sum(n);
return ret;
}
};
不用加减乘除做加法
写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。
首先看十进制是如何做的: 5+7=12,三步走
第一步:相加各位的值,不算进位,得到2。
第二步:计算进位值,得到10. 如果这一步的进位值为0,那么第一步得到的值就是最终结果。
第三步:重复上述两步,只是相加的值变成上述两步的得到的结果2和10,得到12。
同样我们可以用三步走的方式计算二进制值相加: 5-101,7-111
第一步:相加各位的值,不算进位,得到010,二进制每位相加就相当于各位做异或操作,101^111。
第二步:计算进位值,得到1010,相当于各位做与操作得到101,再向左移一位得到1010,(101&111)<<1。
第三步重复上述两步, 各位相加 010^1010=1000,进位值为100=(010&1010)<<1。
继续重复上述两步:1000^100 = 1100,进位值为0,跳出循环,1100为最终结果。
class Solution {//二进制运算!
public:
int Add(int num1, int num2)
{
while(num2 != 0)
{
int sum = num1^num2;
int carray = (num1&num2)<<1;
num1 = sum;
num2 = carray;
}
return num1;
}
};