關於約瑟夫環的思考(一) c

2021-07-22 16:59:10 字數 1586 閱讀 1290

題目:

「約瑟夫環:每隔兩個迴圈刪除陣列元素,求最後刪除者的下標問題」

有乙個陣列a[1000]存放0–1000;要求每隔二個數刪掉乙個數,到末尾時迴圈至開頭繼續進行,求最後乙個被刪掉的數的原始下標位置(原來的數可能是無序的,另外數是否重複從題意無法確定)。

以8個數為例:

0–>1–>2(刪除)–>3–>4–>5(刪除)–>6–>7–>0(刪除),如此迴圈直到最後乙個數被刪除。

考點:

本題的關鍵是如何理解刪除的概念,一種是將其徹底刪除,將後面未刪除的全部前移,這將浪費大量的時間用來移動後續資料;另外一種只是仍然存在但已經失去意義,遍歷過程中不管之

另外乙個關鍵是如何在移動的過程中保持資料的原始下標,因為資料本身可能是無序的,下標和資料可能沒有關係,並且還可能重複。

效能分析:

時間效率:迴圈佇列法由於每次掃瞄的數都是未刪除的,時間整體效率最高;標誌陣列法只是將此數標記為刪除了,但遍歷時仍然要掃瞄;鍊錶法要建立鏈,時間效率低

空間效率:標誌陣列法,未申請額外的空間,空間效率最高;迴圈佇列法至少申請第一次未刪除的空間,另外作為介面函式來實現的話,由於新申請的空間不能與傳入的陣列位址相連,因此有侷限性;鍊錶法額外建立鍊錶,空間效率最低

約束因素:

對於唯讀陣列,普通的標誌法都不能用了,將高位置1遍歷完後清除的方法借鑑意義最高;時間和空間效率最均衡;鍊錶法可以處理唯讀陣列的問題;迴圈佇列法此時無法實現;當然對於標誌法,可以額外申請空間儲存標誌,也可以處理唯讀問題,但空間效率下來了。

方法1:訪問原陣列,置刪除標誌

這題目如果是面試題,那考的就是用陣列,增加難度的。

××××××××××××××××××××××××××××××××

陣列方式一:

const int size=1000;

void arraytest1 (void)

// i用%迴圈計數,終止條件是刪除的只剩最後乙個數了

for(int i=0; (i < size) && (currentsize!=1); i = (i+1) % size)

else if( count==2) // 邏輯有點亂 }

} for(int j=0;j < size;j++) // 浪費時間啊 }

}優化版本:巨集定義意義明確,更改方便,是良好的程式設計習慣,要在筆試面試中展現這種特點

刪除資料時儲存了其位置和實際的資料值,無需最後一次掃瞄

三層判斷條件功能清晰:總數,是否刪除,是否達到間隔值

define size 1000

define step 2

define delflag (size + 1)

void arraytest1opt(void)

// i用%迴圈計數,終止條件是刪除所有的數了

//for(int i=0; currentsize!=0; i=(i+1)%size)

while(currentsize!=0)

}i=(i+1)%size;

} cout<<"the original array location of the last del value is: "<

關於約瑟夫環的解法

關於約瑟夫環的問題,以前用c語言和c 寫過多次,今天看到乙個帖子,覺得方法很巧妙,把它記在這裡,學習一下。摘自http topic.csdn.net u 20090602 13 3878368e 7b47 4937 a383 5ed83ca3a01a.html?39986 問題描述 n個人 編號0 ...

關於約瑟夫環的一些漏洞

include using namespace std typedef struct data typedef struct lnode lnode,linklist intmain intm cout 請輸入設定的上限數 cin m linklist p 驗證是否可以迴圈輸出,即迴圈鍊錶是否建立成...

關於約瑟夫環問題的理解

有序列 0,1,2,3.n 1 可以將0 n 1的序列值理解為任意陣列下標 每次刪除第m個,注意該序列首尾相連,即n 1的下乙個為0,問最後剩下的數字是多少?此問題被稱為約瑟夫環問題,可以用列舉找規律解決,但也可以使用動態規劃來思考 1 記1 n 1序列最後剩下的數字為 f n,m 其中n表示有n個...