在约瑟夫斯问题中,我们有 n 个人,从 1 到 n 编号。每回合你跳过k个人并杀死下一个。通常你打印最后一个幸存者,我对受害者的顺序感兴趣。我尝试根据网上找到的建议使用循环链表来做到这一点。当输入像 n=123456 这样大时,我的算法仍然不够快;k=1000000000。我的时间目标是不到一秒。我认为时间复杂度是 O(nk),因为所有链表操作都是 O(1),并且对于每个人,我必须打印它们的值并可能移动 k 步。我是否应该找到一些不同的策略我是否缺少一些明显的优化技术?
#include <vector>
using namespace std;
struct Node {
int value;
struct Node* next;
};
Node* insertToEmpty(struct Node* last, int x) {
Node* temp = (struct Node*)malloc(sizeof(struct Node));
temp->value = x;
last = temp;
last->next = last;
return last;
}
Node* insert(struct Node* last, int x) {
if (last == NULL) {
return insertToEmpty(last, x);
}
Node* temp = (struct Node*)malloc(sizeof(struct Node));
temp->value = x;
temp->next = last->next;
last->next = temp;
last = temp;
return last;
}
Node* delete2(struct Node* prev, struct Node* current) {
prev->next = current->next;
return current->next;
}
int main() {
int n;
int k;
cin >> n;
cin >> k;
if (n == 1) {
cout << 1;
}
else {
struct Node* curr;
struct Node* prev;
struct Node* last = NULL;
for (int i = 1; i <= n; i++) {
last = insert(last, i);
}
curr = last->next;
prev = curr;
for (int i = 1; i <= k%n; i++) {
prev = curr;
curr = curr->next;
}
do {
cout << curr->value << " ";
curr = delete2(prev, curr);
n--;
for (int j = 0; j < k%n; j++) {
prev = curr;
curr = curr->next;
}
} while (n > 1);
cout << curr->value << endl;
}
}