鏈表常見面試題二:約瑟夫環

面試題1:約瑟夫環

約瑟夫環故事背景:
著名猶太歷史學家 Josephus有過以下的故事:
在羅馬人佔領喬塔帕特後,39 個猶太人與Josephus及他的朋友躲到一個洞中,
39個猶太人決定寧願死也不要被敵人抓到,
於是決定了一個自殺方式,41個人排成一個圓圈,
由第1個人開始報數,每報數到第3人該人就必須自殺,
然後再由下一個重新報數,直到所有人都自殺身亡爲止。
然而Josephus 和他的朋友並不想遵從,Josephus要他的朋友先假裝遵從,
他將朋友與自己安排在第16個與第31個位置,於是逃過了這場死亡遊戲。

問題:怎樣確定16和31的位置

解題思路:

從開始位置遍歷,當指針到報數爲三的位置上時,將第三個位置的節點刪除,然後繼續循環刪除,直到當前節點(指針指向的節點)的後一個節點的next是當前節點時,即留下兩個元素。

如圖所示:

wKioL1aggyfCpxJ8AAAaxYGPcKY290.png

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);
}

wKioL1aghJCyB3L-AAAMWFm-MV8306.png

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章