首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C 猴子選大王(約瑟夫環)陣列標記法:邏輯錯誤修正與改進建議

     編輯:程式設計綜合問答

原始代碼關鍵錯誤

for (int i = 1; i <= m; i++) {
    if (now + 1 > n) now = 1;
    else ++now;
    if (ar[now]) --i; // 已出局者跳過計數
    if (!(ar[now]) && i == m)
        ar[now] = 1; // 標記出局
}
--out;

問題:ar 初始化為 0 代表在圈內,1 代表出局。但邏輯中 if (ar[now]) --i; 導致計數器回退,配合外層 while (out-1) 易陷入無限迴圈或跳過正確位置。

修正版邏輯(陣列標記法)

int n, m, p; // 總數、步長、起始位置
int *ar = calloc(n + 1, sizeof(int)); // 0=在圈內, 1=出局
int remain = n;
int pos = p - 1; // 0-based 索引方便取模

while (remain > 1) {
    int step = 0;
    while (step < m) {
        pos = (pos + 1) % n; // 環狀移動
        if (pos == 0) pos = n; // 1~n 映射
        if (ar[pos] == 0) // 僅對在圈內者計數
            ++step;
    }
    ar[pos] = 1; // 標記出局
    --remain;
}
// 找出剩餘的唯一 0
for (int i = 1; i <= n; ++i)
    if (ar[i] == 0) { printf("%d\n", i); break; }
free(ar);

更優雅:環狀鏈結串列 O(n) 刪除

每次刪除節點只需調整指標,無需掃描已出局位置,適合大數據量。

總結

  • 陣列標記法需小心「計數只針對在圈內者」與「環狀索引取模」。
  • 建議改用鏈結串列或數學遞推公式(f(1)=0; f(i)=(f(i-1)+m)%i)O(n) 直接算出結果。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved