什么是更快的算法来重新排列给定的数字数组

时间:2017-03-08 17:47:18

标签: python algorithm

问题来自代码斗争,其中指出:无数个盒子排成一行并从左到右编号。左边的第一个框是 数字1,下一个方框是2号等,n个球放在n个盒子里,每个盒子只能有一个球。 你想组织球,所以你决定将所有的球安排在一起。他们应该占有一席之地 连续的一套盒子。你可以拿一个球并一次移动到一个空盒子里。

给定一个阵列球,指示放置球的盒子的数量,找到最小数量 需要采取行动来组织球。

实施例

对于球= [6,4,1,7,10],输出应为 球重新排列(球)= 2。

在这个例子中,将球排列在彼此旁边所需的最小移动次数是2.你可以移动 在方框1到方框5中的球和方框10中的球到方框8(或方框3)。

目前我的代码是:

def ballsRearranging(balls):
    ballsLength = len(balls)
    partial = ballsLength//2 #INITIALLY SET TO HALF
    setBalls = set(balls)
    sortedBalls = sorted(balls)
    minimum = 1000000

    #####CHECK IF ITS ALREADY ORGANIZED
    #####FIRST NUM PLUS LENGTH - 1 IS EQUAL TO THE LAST NUM
    if sortedBalls[0]+ballsLength-1 == sortedBalls[-1]:
        return 0

    for i,num in enumerate(sortedBalls):
        #####NO NEED TO GO PASS HALF WAY SINCE THAT AUTOMATICALLY MEANS HALF WILL BE OUT OF RANGE
        #####THIS VALUE DYNAMICALLY CHANGES TO THE SMALLEST FRACTION OF OUT OF RANGE FOUND
        if i >= partial:
            break

        #####IF WE TAKE THIS NUM AS THE BEGINNING, ORDERED BALLS WILL GO UP TO THE RANGE RNG
        rng = range(num,num+ballsLength)
        #####BALLS ALREADY IN THE RANGE RNG, WE WONT BE MOVING THESE BALLS
        inRange = setBalls & set(rng)

        #####BALLS NOT IN RANGE, EACH WILL BE REQUIRED TO MOVE
        #####THE LENGTH OF THIS WILL BE THE NUMBER OF MOVES REQUIRED
        outRange = setBalls - set(rng)

        lenOutRange = len(outRange)
        if lenOutRange < minimum:
            minimum = lenOutRange
            partial = 100*(lenOutRange/ballsLength) #UPDATE THE PARTIAL VALUE

这样可以正常工作,但目前在隐藏测试中超时时限为4秒。基本上我的算法从最小的数字到给定数组的特定部分(分数)。它检查原始集合与给定范围相交的位置。无论哪个具有最少量的超出范围的项目,将是最小数量的更改/重新排列。想知道什么是更好的算法,最好是在python中。

3 个答案:

答案 0 :(得分:1)

首先,你在你的范围和设置结构上花了很多时间。退出检查实际的球位置和空盒子。你所需要的只是移动的数量,而不是要移动的实际球。

例如,给定[1,2,100,103,104,106,9998,9999]之类的东西,你不在乎这四个异常值是什么,或者哪些方框是空的在低100范围内。您所需要的只是数量,4。

解决方案简化为更简单的方法:

Realm Browser

如果你对此有点顽固,可以将其减少到一行。

答案 1 :(得分:1)

此代码小心计算O(n log n)时间内的结果。或者如果球已经排序,则在O(n)时间运行。

它使用卡特彼勒算法:对于每个j,索引到排序的球阵列中,i递增,直到它包含在索引j处的球的n-1内的第一个球。这样可以很容易地计算以第j球结束的范围内的球数。

def balls_rearranging(balls):
    balls.sort()
    best = 0
    i = 0
    for j in xrange(len(balls)):
        while balls[i] <= balls[j] - len(balls):
            i += 1
        best = max(best, j - i + 1)
    return len(balls) - best

print balls_rearranging(range(0, 10000000, 2))

答案 2 :(得分:0)

paul-hankin提供的代码的Java版本

int ballsRearranging(int[] balls) {
Arrays.sort(balls); // sort the array
int i = 0;
int j = 0;
int max = 0;
for(j = 0; j < balls.length;j++) {
    while(balls[i] <= balls[j] - balls.length) {
        i++;
    }
    max = Math.max(max,j-i+1);
}
return balls.length - max;}