1. 程式人生 > >資料結構考研複習--線性表3(約瑟夫環)

資料結構考研複習--線性表3(約瑟夫環)

約瑟夫環這個在一開始看的時候是一個相當蛋疼的問題,本節將為大家講述約約瑟夫環利用迴圈連結串列以及遞迴來進行求解

**約瑟夫環問題的原來描述為,設有編號為1,2,……,n的n(n>0)個人圍成一個圈,從第1個人開始報數,報到m時停止報數,報m的人出圈,再從他的下一個人起重新報數,報到m時停止報數,報m的出圈,……,如此下去,直到所有人全部出圈為止。當任意給定n和m後,設計演算法求n個人出圈的次序。 稍微簡化一下。
問題描述:n個人(編號0~(n-1)),從0開始報數,報到(m-1)的退出,剩下的人繼續從0開始報數。求勝利者的編號。
思路:容易想到的就是用環連結串列來做,構建一個環連結串列,每個結點的編號為0, 1, …… n-1。每次從當前位置向前移動m-1步,然後刪除這個結點。最後剩下的結點就是勝利者。**

我們先來非遞迴的演算法

void JosephusProblem_Solution1(int n, int m)    //n個人,每m退出
{
    int  i = 0;
    LinkList *pm;
    LinkList *pcur;
    LinkList *head = (LinkList *)malloc(sizeof(LinkList));
    LinkList *plast;

    pcur = head;
    pcur->next = head;
    head->data = 0;

    //構造迴圈連結串列
    for (i = 1
; i <10;i++) { pm = (LinkList *)malloc(sizeof(LinkList)); pm->data = i; pcur->next = pm; pcur = pm; } pcur->next = head; //over pcur = head; while(pcur != pcur->next) { //前進m-1步 for (i = 0;i<m-1;i++) { plast =
pcur; pcur = pcur->next; } //刪除 plast->next = pcur->next; free(pcur); pcur = plast->next; } printf("%d ",pcur->next->data); }

這樣的效率顯然不是最高的,時間複雜度o(mn),

接下來看遞迴演算法

公里公道的說,這個遞迴演算法真不好想。

我們先反過來想,如果只有一個人,那麼他一定就是我們要求的,如果有兩個人,那麼他一定跟如果只有一個人的那種情況有關,通過只有一個人我們一定會得到一些線索,同理,我們算n個人的約瑟夫環,必然跟n-1個人的約瑟夫環有關,……一定跟2個人的有關,一定跟一個人的有關。那麼到底有什麼規律呢?這是我們即將要討論的問題

我們假設m = 8 , n = 3

1>>很顯然第一個被刪除的數是(m-1)%n

2>>假設第二輪開始的數是K,那麼只有n-1個人

    K -------> 0
    K+1------> 1
    K+2------> 2    //假設最終他是勝利者
    ...
    k-2-----> n-2

那麼我就知道,這n-1個人,如果說我們現在知道了勝利者,他的編號是X,那麼說他在連結串列中一開始是(k+x)%n,
其中, k = m%n,帶入式子我們知道其實對於n個人,勝利者的編號是(X+m)%n

還記得我們的X是什麼嗎???—>n-1個人時的勝利者

那麼簡而言之,要求n個人最終的勝利者,我們只需要知道n-1個人時候的情況就行了,同理要知道n-1個人必須先求出n-2個人………..必須先求出1個人的情況,一個人編號自然是0,轉化成程式碼就是

fun(1) = 0;
fun(n) = ( fun(n-1) + m ) %n;
int JosephusProblem_Solution2(int n, int m )
{
    if (n==1)
    {
        return 0;
    }
    return (JosephusProblem_Solution2(n-1, m) + m) % n;

}

相關推薦

資料結構考研複習--線性3

約瑟夫環這個在一開始看的時候是一個相當蛋疼的問題,本節將為大家講述約約瑟夫環利用迴圈連結串列以及遞迴來進行求解 **約瑟夫環問題的原來描述為,設有編號為1,2,……,n的n(n>0)個人圍成一個圈,從第1個人開始報數,報到m時停止報數,報m的人出圈,再從

線性Test2

//已知num個人(以編號1,2,3...num分別表示)圍坐在一張圓桌周圍。從編號為point的人開始報數,數到point的那個人出列;他的下一個人又從1開始報數,數到point的那個人又出列;依此規律重複下去,直到圓桌周圍的人全部出列。求新的佇列成員的標號順序 //

資料結構實驗:線性操作一元多項式的運算

title: 線性表操作(一元多項式的運算) date: 2018-10-26 11:22:37 tags: 資料結構 categories: 資料結構 線性表操作(一元多項式的運算) 實驗目的 1、定義線性表的鏈式儲存 2、實現對線性表的一些基本操作和具體函式定義

資料結構課程設計

課程設計題三:約瑟夫(Joseph)環  設計目的:  1.掌握單向迴圈連結串列的建立。 2.掌握單向迴圈連結串列的操作。 設計內容:   編號是1,2,……,n的n個人按照順時針方向圍坐一圈,每個人只有一個密碼(正整數)。一開始任選一個正整數作為報數上限值m,從第一個仍開

單向循

data 單向 struct hit ++ main 指針 printf [] #include<stdio.h>#include<stdlib.h>#define N 10typedef struct node{ int data; st

線性的應用——

依稀記得學C語言的時候寫過這樣的程式碼來實現約瑟夫環(貌似期末的實驗考試就是抽到了這個題,我才不會告訴你我拿了100分捏) #include <stdio.h> void main()

線性及其應用——問題

題目:約瑟夫環(Joseph) ① 問題描述:編號為1到n的n個人,按順時針方向圍成一個環,每人都持有一個密碼(正整數)。任選一個正整數作為報數的上限(設為m),從第一個人開始按順時針方向從1開始順序報數,當報到m時暫停報數,並將報數為m的人輸出,同時將他的密碼作為新的m值

G - And Then There Was One

then star names rule this ret zeros datasets cell Description Let’s play a stone removing game. Initially, n stones are arranged on a ci

And Then There Was One 動態規劃

UVA - 1394 原題目連結 題目描述: Let’s play a stone removing game. Initially, n stones are arranged on a circle and numbered 1, . . . , n clock

Gym 101864 A Criminal

題意:t個樣例,m個人圍成一圈,m的範圍在l到n,一二報數,報數到二的人離開,直至剩下一個人,現在求編號為x的人留下的概率 思路:約瑟夫環有遞推公式,f[1] = 0;當一個人的時候,出隊人員編號為0,這裡編號從0開始,題目是從1開始,f[n] = (f[n-1

hdu 1443 Joseph

題意:約瑟夫環,一共2*k個人,每次報到m出局,前k個是好人,後k個是壞人,求最小的m使得所有的壞人先出局。 解題方案: 模擬,打表,可以維護一個[start,end]區間保護所有的好人,模擬k步。 設p=(m-1)%n,n為當前人數,即p為每次出局的位置(重新排列並對

2019資料結構考研(二)-----線性

知識框架 線性表的基本概念 線性表的定義 線性表是具有相同資料型別的n(n>=0)個數據元素的有限序列,n為線性表的表長,當n=0時,則線性表為空表,線性表的第一個元素稱為表頭,最後一個元素稱為表尾 線性表的基本特點 線性表的元素個數有上限 線性表裡的元

線性---單迴圈連結串列問題

約瑟夫環問題: 已知n個人(以編號1,2,3…n分別表示)圍坐在一張圓桌周圍。從編號為k的人開始報數,數到m的那個人出列;他的下一個人又從1開始報數,數到m的那個人又出列;依此規律重複下去,直到圓桌周圍的人全部出列。 程式碼: #include <i

javaSE (三十四File類和遞迴練習統計資料夾大小、拷貝資料夾、層級列印資料夾、斐波拉契數列、獲取1000階乘全部0和尾部0數目、

1、統計資料夾大小: 思路: 套用之前已經做過的,鍵入一個路徑,若有效則封裝成File類 初始化計數器len, 若資料夾下是檔案,則記錄檔案.length() 若資料夾下是資料夾,遞迴 輸出len 注:遞迴也可以刪除資料夾,但是一定要先刪除裡

【LeetCode & 劍指offer刷題】發散思維題3:62 圓圈中最後剩下的數字問題

【LeetCode & 劍指offer 刷題筆記】目錄(持續更新中...) 62 圓圈中最後剩下的數字(約瑟夫環問題)   題目描述 每年六一兒童節,牛客都會準備一些小禮物去看望孤兒院的小朋友,今年亦是如此。HF作為牛客的資深元老

n個人圍成一圈,從第1個人開始數數,數到3的人出圈,輸出最後剩餘的人編號問題

#include <iostream> #include<stdlib.h> #define MAX 100 using namespace std; int main() { cout << "Hello World!" << endl; i

資料結構(C語言):連結串列,問題

開始學習資料結構,把寫過的程式碼發上來,希望可以給有需要的人一個參考。 //本程式碼由 大漠孤煙 整理編寫,並驗證通過 //求解約瑟夫問題,涉及到連結串列節點的生成,節點的插入和刪除,對理解連結串列非常有好處 //N個節點圍城一圈,從第一個節點開始計數(1),每數

下的

eno 鏈表 lis main brush return invalid lin java 首先把上面的雙向鏈表改為循環雙向鏈表 public class MyLinkedList2<E> { /** * 第一個 */ t

的應用——

hide creat rip urn nes scan hid fadein repr 題目: 報數,共n個人 從1編號,依次報號,報到m出隊,再接著從下一個人開始數,依次輸出出隊的人。 #include<stdio.h> #incl

F - System Overload問題

point ould ica cat random ppi out eterm img Description Recently you must have experienced that when too many people use the BBS simultan