数组索引与其长度的关系

时间:2017-08-27 06:15:04

标签: javascript arrays data-structures

我在数组中练习了一些问题的编码: 这是我的问题: https://www.hackerrank.com/challenges/array-left-rotation/problem

这是我的解决方案:

function leftRotation(a, d) {
    // Complete this function
    var result = new Array(a.length);
    for (i = 0; i < a.length; i++) {
        var what = i - d;
        if (what < 0) {
            result[a.length + what] = a[i];
        } else {
            result[what] = a[i];
        }
    }
    return result;
}

我的解决方案通过了所有测试用例,但我不知道为什么它是正确的。

详细说明,在此代码块中

if (what < 0) {
    result[a.length + what] = a[i];
}

我通过检查实数来找到该公式,并且在很多情况下它是正确的,然后我实现了它。但我不知道它为什么是正确的,因为我从未见过索引数组长度之间的任何关系。如果你知道,请帮忙解释一下。

P / s:如果您有解决此问题的任何方法(我的意思是可解释的解决方案,而不是像我这样),请帮助将其发布在此处。

提前感谢一大堆!

2 个答案:

答案 0 :(得分:1)

很难理解代码如何工作的一个很好的部分原因是命名不佳。我使用了与您提供的完全相同的逻辑/代码,但重命名的内容更加清晰。对于任何事情,what都是一个特别糟糕的名称选择。

请注意,我为a.length创建了一个变量,而不是调用它3次。我还使用了const而不是var,因为HackerRank支持Node.js. const对于在声明后不会重新分配的变量很有用,例如在这种情况下。对于可以重新分配的变量,请使用let代替constvar

我在代码中包含了解释性注释。希望这可以帮助。

function leftRotation(inputArr, rotations) {
    // calculate length once and reuse it
    const inputArrLength = inputArr.length;
    // we will put the values with their new indexes in this array
    const rotatedArr = new Array(inputArrLength);
    // iterate over index (idx) of each value in inputArr
    for (idx = 0; idx < inputArrLength; idx++) {
        // find out what the new index will be after rotating
        const newIdx = idx - rotations;
        // set index to the back of the array if it has to "wrap around"
        if (newIdx < 0) {
            // newIdx is negative so adding it actually subtracts it from length
            rotatedArr[inputArrLength + newIdx] = inputArr[idx];
        }
        // otherwise just set the new index 
        else {
            rotatedArr[newIdx] = inputArr[idx];
        }
    }
    return rotatedArr;
}

在考虑这个问题的同时,我想出了一个更简单的算法,我认为它更直观(也可能更快)。这类似于人们如何将物体物理地滑动到左侧并将那些从表面/阵列上掉落的物体放在后面/右侧。它具有较少的算术运算,因为旋转偏移仅计算一次,然后用于划分索引。它还通过了所有测试用例。

function leftRotation(inputArr, rotations) {
    const inputArrLength = inputArr.length;
    const rotatedArr = new Array(inputArrLength);
    const wrapAroundIdxOffset = inputArrLength - rotations;
    // we can just "slide" to the left any values' idx that 
    // don't need to wrap around the beginning/left of array
    for(idx = rotations; idx < inputArrLength; idx++) {
        rotatedArr[idx - rotations] = inputArr[idx];
    }
    // and the others get wrapped around
    for(idx = 0; idx < rotations; idx++) {
        rotatedArr[wrapAroundIdxOffset + idx] = inputArr[idx];
    }
    return rotatedArr;
}

答案 1 :(得分:0)

在问题中提到 d&lt; = n

所以假设你想要将第0个索引旋转3个位置,假设数组的长度为n。

第一次旋转,现在元素在n-1,在第二次旋转之后它将在n-2,在第3次旋转之后它将在n-3。

所以我处于第0个索引并想要左旋3次,对于这种情况

what = -3;

因此

result[n-3] = a[0];

这正是我们想要的,现在第一和第二指数可以类似地旋转到 n-2 n-1 指数。

这就是为什么你的解决方案有效,因为d&lt; = n而我们只是想把它们放在什么位置

使用数组是

[1, 2, 3, 4, 5]

让我们将这个数组连接到自身,这样数组现在就是

[1, 2, 3, 4, 5, 1, 2, 3, 4, 5]

现在左移2意味着我们需要从索引 2 7 的数组,即

[3, 4, 5, 1, 2]

现在你可以看到a [5] = a [0]或a [i + n] = a [i],在结果数组中我们将删除[0]和[1]所以现在< / p>

  

a [5]将成为[5-2]而[6]将成为[6-2]或[5-1]或 a [n +(id)]