[英]How to dynamically fill a triangular two-dimensional array?
我的任务需要基于三角矩阵的数值计算(模数不超过9,数组的大小不能超过15):
1 2 3 4 5
7 8 9 0
4 5 6
2 3
1
我认为将数据存储在二维三角形阵列中将是最方便的。
UPD :随后,我将需要选择从第二层的任何元素到最上层的最大路径(该路径只能沿对角线移动,而不能垂直或水平向上移动)。 这是类似于最大路径问题的任务,该问题的解决方案使用2D数组看起来最简单。
在这里我一下子遇到了几个问题:
1)如何甚至静态创建三角形数组?
现在我正在做这样的事情:
let numbers = [1, 2, 3, 4, 5, 6]; function fillArray(nums, layer) { let arr = []; for(let k = 0; k < nums.length;) { for (let i = 0; i < layer; i++) { arr[i] = []; for (let j = 0; j <= i; j++) { arr[i][j] = nums[k]; k++; } } } return arr; } console.log(fillArray(numbers,3));
也许这是正确的,但是它看起来太麻烦了,此外,在我看来,我可以即时计算图层。 递归解决方案可能在这里看起来更好。
2)如何确定何时创建新的嵌套数组?
静态地,一切都非常清楚,但是如果我有一个数组,可以说它是这样填充的: [ [1], [1, 2], [1, 2] ]
然后如何确定创建新嵌套的时刻数组,即,将当前一个填充到此状态: [ [1], [1, 2], [1, 2, 3] ]
,例如,如果要输入新元素,则在填充前一个元素后创建以下内容一个: [ [1], [1, 2], [1, 2, 3], [1, 2, 3, 4] ]
如果您的计算是随机使用三角矩阵,则可以显式计算行/列索引:
function row_col_from_index(i) {
let row = 0.5 * ((8*i + 1)**0.5 - 1),
col = i - row*(row+1)/2;
return [row, col];
}
function index_from_row_col(row, col) {
return row*(row+1)/2 + col;
}
那么您可以在需要时懒惰地在矩阵中创建所需的行
let matrix = [];
...
let [row, col] = row_col_from_index(i);
(matrix[row]||(matrix[row]=[]))[col] = data;
通过求解来计算索引的行/列的“魔术”公式
x*(x+1)/2 = n
您可以执行摘要中所示的操作。 但这绝对比for循环慢,并且不使用递归...测量.reduce .reduce()
与递归解决方案(如@VLAZ .reduce()
性能将非常有趣。
下面的代码要做的是填充各层直到它们填满,然后根据上一层+ 1的长度创建一个新层:
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]; let layer = 0; const fillArray = input => input.reduce((acc, num) => { if ( acc.length ) { if ((acc[layer] || []).length !== acc[layer-1].length+1) { // fill current child-array until full acc[layer] = (acc[layer] || []).concat(num); } else { // start next child-array with current number layer++; acc[layer] = [num]; } } else { // initialize with first child-array layer++; acc = [[num]]; } return acc; }, []); console.log(fillArray(numbers));
编写函数相同函数的另一种“传统”方法:
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]; let layer = 0; function fillArray(input) { return input.reduce(function(acc, num) { if ( acc.length ) { if ( (acc[layer] || []).length !== acc[layer-1].length+1 ) { // fill current child-array until full acc[layer] = (acc[layer] || []).concat(num); } else { // start next child-array with current number layer++; acc[layer] = [num]; } } else { // initialize with first child-array layer++; acc = [[num]]; } return acc; }, []); } console.log(fillArray(numbers));
是的,您可以在此处采用递归算法,并在没有更多值可绘制时停止,否则从输入数组的开头获取一个不断增长的切片,然后使用下一次剩余的内容:
let numbers = [1, 2, 3, 4, 5, 6]; function fillArray(nums, result = [], size = 1) { if (nums.length === 0) return result; const currentItem = nums.slice(0, size); const remainder = nums.slice(size); result.push(currentItem); return fillArray(remainder, result, size + 1); } console.log(fillArray(numbers));
如果需要,可以将其进一步缩短为仅两行
let numbers = [1, 2, 3, 4, 5, 6]; function fillArray(nums, result = [], size = 1) { if (nums.length === 0) return result; return fillArray( nums.slice(size), [...result, nums.slice(0, size)], size + 1 ); } console.log(fillArray(numbers));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.