微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在On

如何解决如何在On

是否可以在 O(n)的约瑟夫斯问题中打印出移除顺序

示例

人数为n = 7,跳过人数为k = 3。淘汰的顺序为:

3,6,2,7,5,1,4

我已经尝试过该算法,但仅适用于n <= 10^4,我需要一种算法,该算法可以在 1秒以内

n <= 10^8

解决方法

有一种使用有序集的方法

(https://www.geeksforgeeks.org/ordered-set-gnu-c-pbds/):

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。