面试题1:约瑟夫环
约瑟夫环故事背景:
著名犹太历史学家 Josephus有过以下的故事:
在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,
39个犹太人决定宁愿死也不要被敌人抓到,
于是决定了一个自杀方式,41个人排成一个圆圈,
由第1个人开始报数,每报数到第3人该人就必须自杀,
然后再由下一个重新报数,直到所有人都自杀身亡为止。
然而Josephus 和他的朋友并不想遵从,Josephus要他的朋友先假装遵从,
他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。
问题:怎样确定16和31的位置
解题思路:
从开始位置遍历,当指针到报数为三的位置上时,将第三个位置的节点删除,然后继续循环删除,直到当前节点(指针指向的节点)的后一个节点的next是当前节点时,即留下两个元素。
如图所示:
pLinkNode JoseCycle(pList *pHead, int num)
{
assert(pHead);
pLinkNode cur = *pHead;
pLinkNode del = NULL;
int count = 0;
while (1)
{
count = num;
if (cur == cur->next->next) //当前节点的后一个节点的next是当前节点时,结束循环
{
break;
}
while (--count) //找到第num个元素
{
cur = cur->next;
}
del = cur->next;
cur->data = cur->next->data;
cur->next = cur->next->next;
free(del); //删除第num个元素
del == NULL;
}
*pHead = cur;
return cur;
}
测试函数:
void Test13() // 测试约瑟夫环
{
pList l1;
int i = 0;
InitLinkList(&l1);
for (i = 1; i <= 41; i++)
{
PushBack(&l1, i);
}
pLinkNode pos = Find(l1,41); //查找元素,Find函数在单链表的实现中
pos->next = l1; //构建环
pos=JoseCycle(&l1,3);
printf(" %d \n", pos->data);
printf(" %d \n", pos->next->data);
}
转载于:https://blog.51cto.com/haipi/1737171