剑指offer(46~48)孩子们的游戏--求1+2+3+...+n--不用加减乘除做加法

孩子们的游戏(圆圈中最后剩下的数)

每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此。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;
    }
};

牛客网链接

评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值