繁体   English   中英

如何动态填充三角形二维数组?

[英]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

求解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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM