数据结构和算法经典100题-第18题

这是一个约瑟夫环问题。Okay看题目吧。
第18题
题目:n个数字(0,1,…,n-1)形成一个圆圈,从数字0开始,
每次从这个圆圈中删除第m个数字(第一个为当前数字本身,第二个为当前数字的下一个数字)。
当一个数字删除后,从被删除数字的下一个继续删除第m个数字。
求出在这个圆圈中剩下的最后一个数字。


题目分析:第一时间想到的方法是创建一个循环链表或者是一个带有循环数组这样一个循环数据结构来模拟整个过程。
代码可能是这样的:

int func(int n,int m) {
#define GO_ON if(i == n){i = 0;} else {i++;}
    int i;

    // assert
    if (0 > m ) {
        return -1;
    }

    // init circular array
    int *array = (int*)malloc(sizeof(int)*n);
    for (i = 0; i < n; i++) {
        array[i] = i;
    }

    // define variable for ergodic
    int removeNum = 0;// 环中剩余一个元素时结束
    int tmp = 0; // 累加到m时,删除
    i = 0;

    // ergodic
    while ( n -1 == removeNum) {
        if (-1 == array[i]) {
            GO_ON;
            continue;
        }

        if (m == tmp) {
            array[i] = -1;
            removeNum--;
            tmp = 0;
        } else {
            tmp++;
        }

        GO_ON;
    }

    return array[i];
}

OKay,but亲们这不是最简单的方法,从网络上看到一个解决这种类似的约瑟夫环问题更简单的算法:
f(n,m)={ 0 n=1

     [f(n-1,m)+m]%n     n>1
   }

感兴趣的亲们可以到这个网址看一下,推导的过程:
http://zhedahht.blog.163.com/blog/static/2541117420072250322938/

OK,有个这个递推公式,那么解决这个问题,不论是用迭代法还是递归法都很好解决了,下面给出本人根据以上公式写得代码:

int recursion(int n,int m)  {
    if (0 == n) {
        return 0;
    }

    return (recursion(n-1, m) + m) % n;
}

int foo(int n,int m) {
    if (0 == n) {
        return 0;
    }
    int k = 0;
    for (int i = 1; i < n; i++) {
        k = (k + m) % i;
    }
    return k;
}

Okay,路漫漫啊。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值