鉴于两个数组arr1
和arr2
两个具有相同的项目,但排序方式不同,如何制作一个列表,列出了arr1
所需的项目移动操作次数最少匹配arr2
?
执行此操作的函数/算法应该接受我的两个数组作为唯一参数,并返回如下数组:
[
[1,5],
[3,0],
[7,2]
]
上述数组将被解释为“将索引1处的项目移至索引5,然后将索引3处的项目移至索引0,最后将索引7处的项目移至索引2.”
通过项目移动操作,我的意思如下:
function arrayMove(array, from, to) {
return array.splice(to, 0, array.splice(from, 1)[0]);
}
当项目从索引a
移动到索引b
时,索引a
之后的项目“向下滑动”,因此索引为a + 1
的项目现在具有索引{ {1}},当项目在索引a
处重新添加时,具有b
的项目将向上滑动,以便具有索引index >= b
的项目现在具有索引b
。
随意提供您的算法JS或伪代码,任何帮助赞赏。
答案 0 :(得分:1)
这与我edit distance problem有关。也许你可以利用Wagner-Fischer algorithm。
答案 1 :(得分:1)
或许这样的事情?
的Javascript
// swap two elements in an array by their indexes a and b and
// return an array of the swapped coordinates.
function swap(arr, a, b) {
// assign the value at index a to temp
var temp = arr[a];
// assign the value at index b to index a
arr[a] = arr[b];
// assign the value of temp to the value at index b
arr[b] = temp;
// coordinates of move
return [a, b];
}
// return an array of moved coordinates
function minMoves(arr1, arr2) {
// take a shallow copy of arr2 so that the original is not modified
arr2 = arr2.slice();
// apply a function against an accumulator (moves) for each value of
// the array (arr1) (from left-to-right)
return arr1.reduce(function (moves, item, index) {
// if the values of each array at the index are not the same
if (item !== arr2[index]) {
// swap the current indexed element of arr2 with the value of
// the correct element as indexed in arr1. Add the moved
// coordinates to the beginning of the accumulator
moves.unshift(swap(arr2, index, arr2.lastIndexOf(item)));
}
// return the accumulater for the next iteration
return moves;
}, []);
}
var before = [1, 5, 6, 3, 2, 4, 7, 8, 9, 0],
test = before.slice(),
after = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0],
moves = minMoves(before, after);
console.log('moves: ' + JSON.stringify(moves));
moves.forEach(function(move) {
swap(test, move[0], move[1]);
});
console.log('Should be ordered nicely: ' + JSON.stringify(test));
输出
moves: [[3,5],[2,5],[1,4]]
Should be ordered nicely: [1,2,3,4,5,6,7,8,9,0]
上
这就是我要做的,它不是基于任何已被证明是最优的算法研究。
以下是使用arrayMove
方法代替swap
的Javascript
function arrayMove(array, from, to) {
return array.splice(to, 0, array.splice(from, 1)[0]);
}
// return an array of moved coordinates
function minMoves(arr1, arr2) {
// take a shallow copy of arr2 so that the original is not modified
arr2 = arr2.slice();
// apply a function against an accumulator (moves) for each value of
// the array (arr1) (from left-to-right)
return arr1.reduce(function (moves, item, index) {
var last;
// if the values of each array at the index are not the same
if (item !== arr2[index]) {
// swap the current indexed element of arr2 with the value of
// the correct element as indexed in arr1. Add the moved
// coordinates to the beginning of the accumulator
last = arr2.lastIndexOf(item);
arrayMove(arr2, last, index);
moves.unshift([index, last]);
}
// return the accumulater for the next iteration
return moves;
}, []);
}
var before = [1, 5, 6, 3, 2, 4, 7, 8, 9, 0],
test = before.slice(),
after = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0],
moves = minMoves(before, after);
console.log('moves: ' + JSON.stringify(moves));
moves.forEach(function(move) {
arrayMove(test, move[0], move[1]);
});
console.log('Should be ordered nicely: ' + JSON.stringify(test));
输出
moves: [[3,4],[2,5],[1,4]]
Should be ordered nicely: [1,2,3,4,5,6,7,8,9,0]
上
最后用jsPerf比较两种方法。