📜  O(N logN) 中约瑟夫斯问题的去除顺序

📅  最后修改于: 2022-05-13 01:56:06.015000             🧑  作者: Mango

O(N logN) 中约瑟夫斯问题的去除顺序

给定N个孩子围成一圈等待被执行,和一个数字K ,表示顺时针方向跳过K-1个孩子,在圈内杀死第K孩子,然后执行(K+1 ) th child 开始,任务是打印如果从第一个孩子开始执行,将在第i 步中被杀死的孩子。

注意:默认情况下,最后一个孩子最后被认为是死的。

例子:

Naive Approach:最简单的想法是使用一个向量来存储剩余孩子的位置。然后在向量的大小大于1时进行迭代,并在每次迭代中从向量中删除所需的位置。

时间复杂度: O(N 2 )
辅助空间: O(N)

高效方法:上述方法可以使用有序集进行优化。请按照以下步骤解决问题:

  • 初始化一个有序集,比如V ,并将[1, N]范围内的元素插入V
  • 初始化一个变量,比如pos0 ,以存储被移除元素的索引。
  • 迭代直到集合的大小, 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)