有一种使用有序集的方法
(https://www.geeksforgeeks.org/ordered-set-gnu-c-pbds/):
- 初始化一个有序集合V,并将 [1, N] 范围内的元素插入到 V 中。
- 初始化一个变量,比如pos为0,以存储被移除元素的索引。
- 迭代直到V的大小大于1,并执行以下步骤:
- 将集合的大小存储在变量中,例如X
- 将pos的值更新为(pos + K) % X
- 打印V中pos指向的元素,然后擦除
- 将 pos更新为pos %V.size()
- 打印存储在集合 V 开头的最后一个元素
这是代码:
#include <iostream>
using namespace std;
// Header files, namespaces to use
// ordered set
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
#define ordered_set \
tree<int, null_type, less<int>, rb_tree_tag, \
tree_order_statistics_node_update>
// Function to find the person who
// will get killed in the i'th step
void orderOfExecution(int N, int K)
{
// Create an ordered set
ordered_set V;
// Push elements in the range
// [1, N] in the set
for (int i = 1; i <= N; ++i)
V.insert(i);
// Stores the position to be removed
int pos = 0;
// Iterate until the size of the set
// is greater than 1
while (V.size() > 1) {
// Update the position
pos = (pos + K) % (int)V.size();
// Print the removed element
cout << *(V.find_by_order(pos)) << ' ';
// Erase it from the ordered set
V.erase(*(V.find_by_order(pos)));
// Update position
pos %= (int)V.size();
}
// Print the first element of the set
cout << *(V.find_by_order(0));
}
int main()
{
int N = 5, K = 2;
// Function Call
orderOfExecution(N, K);
return 0;
}
时间复杂度:O(N * log(N))
为了更好地理解,我建议查看此视频:
https://youtu.be/KnsDFCCBJbY