O(N logN) 中约瑟夫斯问题的去除顺序
给定N个孩子围成一圈等待被执行,和一个数字K ,表示顺时针方向跳过K-1个孩子,在圈内杀死第K个孩子,然后执行(K+1 ) th child 开始,任务是打印如果从第一个孩子开始执行,将在第i 步中被杀死的孩子。
注意:默认情况下,最后一个孩子最后被认为是死的。
例子:
Input: N = 5, K = 2
Output: 3 1 5 2 4
Explanation:
Initially, the arrangement is {1, 2, 3, 4, 5} and the operations performed are:
- Counting from 1, the Kth child is 3. So the 3rd child gets killed. After that, the children left to be executed are {1, 2, 4, 5}, and then execution of child 4 begins.
- Counting from 4, the Kth child is 1. So the first child gets killed. After that, the children left to be executed are {2, 4, 5}, and then execution of child 2 begins.
- Counting from 2, the Kth child is 5. So the fifth child gets killed. After that, the children left to be executed are {2, 4}, and then execution of child 2 begins.
- Counting from 2, the Kth child is 2. So the second child gets killed. After that, the child left to be executed is 2, and then execution of child 4 begins.
- Finally, child 4 is the only remaining child. So the child will be killed.
Input: N = 7, K = 2
Output: 3 6 2 7 5 1 4
Naive Approach:最简单的想法是使用一个向量来存储剩余孩子的位置。然后在向量的大小大于1时进行迭代,并在每次迭代中从向量中删除所需的位置。
时间复杂度: O(N 2 )
辅助空间: O(N)
高效方法:上述方法可以使用有序集进行优化。请按照以下步骤解决问题:
- 初始化一个有序集,比如V ,并将[1, N]范围内的元素插入V 。
- 初始化一个变量,比如pos为0 ,以存储被移除元素的索引。
- 迭代直到集合的大小, V大于1 ,并执行以下步骤:
- 将集合的大小存储在一个变量中,比如X 。
- 将pos的值更新为(pos + K) % X 。
- 在V中打印pos指向的元素,然后将其擦除。
- 将 pos 更新为pos %V.size()。
- 最后,完成上述步骤后,打印出集合V开头存储的最后一个元素。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Header files, namespaces to use
// ordered set
#include
#include
using namespace __gnu_pbds;
#define ordered_set \
tree, rb_tree_tag, \
tree_order_statistics_node_update>
// Function to find the child who
// will get killed in the ith 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));
}
// Driver Code
int main()
{
// Given input
int N = 5, K = 2;
// Function Call
orderOfExecution(N, K);
return 0;
}
输出
3 1 5 2 4
时间复杂度: O(N * log(N))
辅助空间: O(N)