调试hackerrank周代码Lazy Sorting

时间:2016-06-29 03:57:06

标签: algorithm probability

我正在对hackerrank(https://www.hackerrank.com/contests/w21/challenges/lazy-sorting)做一个问题,我很困惑为什么我的代码不符合要求。问题是:

洛根正在打扫他的公寓。特别是,他必须以非递减顺序对N个正整数排序他最喜欢的序列P.他在漫长的一天中感到疲惫,所以他发明了一种简单的方法(在他看来)做这项工作。他的算法可以通过以下伪代码来描述:

while isNotSorted(P) do {   
    WaitOneMinute();
    RandomShuffle(P)
}

您能否确定Logan等待分类的预计分钟数?

输入格式:

第一行包含一个整数N,表示置换的大小。第二行包含N个以空格分隔的整数,用于描述序列当前顺序中的各个元素,P_0,P_1 ...... P_N- 1。

约束: 2 <= N <= 18 1&lt; = P_i&lt; = 100

输出格式:

打印预期的分钟数Logan必须等待P进行排序,四舍五入到小数点后6位(即1.234567格式)。

示例输入:

2
5 2

示例输出:
2.000000

解释

随机shuffle后有两种可能的排列,每种排列的概率为0.5。在第一分钟之后获得序列的概率是0.5。在第二分钟之后将被分类的概率是0.25,概率将在第三分钟之后被分类为0.125,依此类推。因此预期的分钟数等于:

i * 2 ^ -i的总和,其中i从1变为无穷大= 2

我用c ++编写了我的代码如下:

#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
#include <map>
using namespace std;
int main() {
/* Enter your code here. Read input from STDIN. Print output to STDOUT */ 

    map <int, int> m; //create a map to store the number of repetitions of each number
    int N;  //number of elements in list
    //calculate the number of permutations
    cin >> N;
    int j;
    int total_perm = 1;
    int temp;
    for (int i = 0; i < N; i++){
        cin >> temp;
        //if temp exists, add one to the value of m[temp], else initialize a new key value pair
        if (m.find(temp) == m.end()){
            m[temp] = 1;
        }else{
            m[temp] += 1;
        }
        total_perm *= i+1;
    }
    //calculate permutations taking into account of repetitions
    for (map<int,int>::iterator iter = m.begin(); iter != m.end(); ++iter)
    {
        if (iter -> second > 1){
            temp  = iter -> second;
            while (temp > 1){
                total_perm = total_perm / temp;
                temp -= 1;
            }
        }
    }

    float recur = 1 / float(total_perm);
    float prev;
    float current = recur;
    float error = 1;
    int count = 1;
    //print expected number of minutes up to 6 sig fig
    if (total_perm == 1){
        printf("%6f", recur);
    }else{
        while (error > 0.0000001){
            count += 1;
            prev = current;
            current = prev + float(count)*float(1-recur)*pow(recur,count-1);
            error = abs(current - prev);
        }
        printf("%6f", prev);

    }
    return 0;
}

我不太关心比赛,更多的是关于为我学习,所以如果有人能指出我错在哪里,我真的很感激。

2 个答案:

答案 0 :(得分:0)

不幸的是我不熟悉C ++,所以我不确切知道你的代码在做什么。但是,我确实解决了这个问题。这是相当厚颜无耻的,我认为他们提出问题的方式只是让他们感到困惑。因此,这里的重要知识是,对于具有概率p的事件,预期的试验次数直到成功为1 / p。由于每次试验花费我们一分钟,这意味着我们可以找到预期的试验次数,并在最后添加“.000000”。

那你怎么做的?那么数字的每个排列都可能同样发生,这意味着如果我们能找到有多少排列,我们就可以找到p。然后我们拿1 / p来获得E [时间]。但请注意,每个排列的概率为1 / p,其中p是排列的总数。所以真的E [时间] =排列数。我把剩下的留给你了。

答案 1 :(得分:0)

这只是一个简单的问题。 这个问题看起来像bogo排序。 给定数组有多少独特的排列可能?在示例情况下,可能存在两种排列,因此任何一种排列发生的预期时间是2.000000。考虑到任何重复的数字,将此方法扩展到通用案例。

然而在问题中,数字可以重复。这减少了唯一排列的数量,从而减少了答案。

只需查找数组的唯一排列数,最多6位小数。这是你的答案。

考虑一下数组是否排序然后发生了什么?

E.g 如果测试用例是

5 5

5 4 3 2 1

然后ans将是120.000000(5!/ 1!)

5 5

1 2 3 4 5

然后你的问题中的ans将是0.000000。

5 5

2 2 2 2 2

然后ans也将是0.000000

5 5

5 1 2 2 3

然后ans是60.000000

一般情况下,如果数组没有排序:N!/ P!* Q!..等等..

这是另一个有用的链接:

https://math.stackexchange.com/questions/1844133/expectation-over-sequencial-random-shuffles