您的位置:首页 > 其它

算法习题18:约瑟夫环(n个数字(0,1,…,n-1)形成一个圆圈)

2013-10-17 15:47 267 查看
题目:n个数字(0,1,…,n-1)形成一个圆圈,从数字0开始,
每次从这个圆圈中删除第m个数字(第一个为当前数字本身,第二个为当前数字的下一个数字)。
当一个数字删除后,从被删除数字的下一个继续删除第m个数字。
求出在这个圆圈中剩下的最后一个数字。

--------------------------------

约瑟夫环是一个数学的应用问题:已知n小伙伴(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人只剩最后一个小伙伴。。找出这个小伙伴把!

(1)方法一

当然是直接模拟这个过程:可以利用一个链表(环形)来模拟,也可以直接用数组,记得%n就好了

//============================================================================
// Name        : YSFCircle.cpp
// Author      : YLF
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <iostream>
using namespace std;

void Solution1(int *arr, int length, int m);

int main() {
int arr[10] = {0,1,2,3,4,5,6,7,8,9};
int m = 5;

Solution1(arr,10,m);
return 0;
}

/*
* simulate the process
*/
void Solution1(int *arr, int length, int m){
int i = 0;
int index = length;
int mIndex = m;
while(index>1){
mIndex = m;
while(mIndex > 0){
if(arr[i] != -1){
mIndex--;
if(mIndex == 0)
arr[i] = -1;
}
i = (i+1)%length;
}
index--;
}
for(i=0;i<length;i++)
if(arr[i] != -1)
cout<<arr[i];
}


(2)约瑟夫算法

约瑟夫这个算法确实很巧妙!

看了好几篇文章,都觉得抄得太high了,着实让智商不够的我纠结了一阵子。。

其实这里就是一个回溯的感觉

假设我们现在要先找到n个元素里第m个 那么就是a[m-1]这个元素被删除了,然后数组变换如下:

0    1    ...  m-2    m-1  m  ...     n-1

0    1    ...   m-2    m   m+1   ...  n -1

我们接下来是从arr[m]  这个元素开始了,如果我们重新把这个新数组看成一个新数组,那么可以表示如下

m    m+1   ...     n-1     0    1    ...        m-2   数组一

如果依然从0开始标记:(对应上面这个数组)

0       1     ....   n-m-1 n-m  n-m+1       n-2   数组二

我们发现,如果这时候数组二和数组一是一一对应的,如例如数组二的   第n-m+1元素就是数组一的 1元素所以如果数组二的元素位置记为x,在数组一的元素位置记为x'

则有数组二-----》数组一关系    x' = (x+m)%n

那同理,数组三 ---->数组二 就有  x' = (x+m)%(n-1)

所以,如果我们知道了最后一个数组(也就是只剩最后一个元素,他的位置标记当然是0 了 ,一个元素的数组下标就是0),就可以推出剩下两个元素里该元素的位置。。。。以此类推,就可以得到最后剩下那个元素在初始数组里的位置了。。。

确实不好解释,大家想想,就是假设我知道了,最后剩下的那个元素,也就是最后剩下的数组,这个数组我们重新排序了,那这个元素在这个数组的下标肯定是0,好了,我们可以通过这个数组推出该元素在上一个数组(含有两个元素)的坐标,然后再推出上上个数组里的坐标。。。。。

_______________________|

            0                          if i==1  |

f(i) ={                                            |

            (f(i-1)+m)%i       if  i>1   |

----------------------------------------|

/*
* using YSF Algorithm
*/
void Solution2(int *arr, int length, int m){
int last = YSF(length,m);
cout<<arr[last];
}

int YSF(int i , int m){
if(i == 1)
return 0;
return (YSF(i-1, m)+m)%i;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐