【问题标题】:Zigzag traversal of a two-dimensional array二维数组的锯齿形遍历
【发布时间】:2021-09-30 12:00:12
【问题描述】:

我需要以之字形遍历一个二维数组,并沿途挑选元素:

发件人:

[['????','????','????','????'],
 ['????','????','????','????'],
 ['????','????','????','????'],
 ['????','????','????','????']]

收件人:

['????','????','????','????','????','????','????','????','????','????','????','????','????','????','????','????']

我的方法是使用 for 循环,检查第一个数组的每个索引并将其与下一个数组的索引进行比较,然后如果该数字更大,则将其推入新的一维数组。

解决此问题的最佳方法是什么?您是否有一些资源可以了解有关此模式的更多信息?

【问题讨论】:

  • 好的,等我试试。数组可以包含重复的条目吗?
  • 是的,你是对的
  • 你真的认为你接受的答案是正确的吗?
  • @Alan 你问的是 zigzag 方法。对吗?
  • 是的,曲折法

标签: javascript traversal


【解决方案1】:

旧答案:

您可以将.flat() 方法用于javascript 数组。 Array.flat()

let array = [
    [1, 3, 4, 10],
    [2, 5, 9, 11],
    [6, 8, 12, 15],
    [7, 13, 14, 16],
]
const flatArray = array.flat()
flatArray.sort((a,b)=>a-b)
console.log(flatArray)

更新答案: 问题更新输出后

const items = [
    [1, 3, 4, 10],
    [2, 5, 9, 11],
    [6, 8, 12, 15],
    [7, 13, 14, 16],
];

/*const items =  [
  [? , ? , ? , ? ],
  [? , ? , ? , ? ],
  [? , ? , ? , ? ],
  [? , ? , ? , ? ],
]*/

function zigZag(arr) {
    let array = []
    const itemCounts = arr.reduce((pre, cur)=> pre+cur.length,0)    
    for(let i=0; i<itemCounts; i+=1){
        let round = []
        for(let j=0; j<arr.length; j+=1){
            if(arr[j].length){
                round.push({
                    value: arr[j][0],
                    row:j
                })
            }
            
        }
        const minValue = Math.min(...round.map(item=>item.value))
        const target = round.find(item=>item.value == minValue)
        array.push(arr[target.row].shift())
    }    
    return array;
};

console.log(zigZag(items))

【讨论】:

  • 哦,感谢您介绍flat 函数。
  • 但这只是对数组进行升序排序,这里的挑战是根据之字形方式对数组进行排序
  • @Alan 哦,曲折的方式。好的,但从你的输出来看,我认为这不是曲折的。你的输出是正确的?
  • 是的,你是对的,输入和输出可能会混淆,我将其更改为更好地理解问题
  • @Alan 谢谢,这样更好。我会更新我的答案并通知你
【解决方案2】:

更新答案

此函数将以 zigZag 方式合并数组。

这里我展示了 2 个具有不同数据类型值的数组的示例。

function zigZag(array) {
    let arrayLength = array.length;
    let arrayItemLength = array[0].length;
    let result = [];
    let flag = true;

    for(let i = 0; i < (arrayLength + (arrayLength / 2) + 1) ; i++) {
        if(i < arrayItemLength) {
            let length = (i + 1);
            let ii = i;
            for(let j = 0; j < length; j++) {
                if(flag == true) result.push(array[j][ii]);
                else result.push(array[ii][j]);
                ii-=1;
            }
        }else {
            let ii = (i + 1) - arrayItemLength;

            for(let j = arrayItemLength - 1; j > i - arrayItemLength; j--) {
                if(flag == true) result.push(array[ii][j]);
                else result.push(array[j][ii]);
                ii+=1;
            }
        }
        if(flag == true) flag = false;
        else flag = true;
    }

    return result;
}

let array = [
    ["?" , "?" , "?" , "?" ],
    ["?" , "?" , "?" , "?" ],
    ["?" , "?" , "?" , "?" ],
    ["?" , "?" , "?" , "?" ],
];

let array_1 = [
    [1, 3, 4, 10],
    [2, 5, 9, 11],
    [6, 8, 12, 15],
    [7, 13, 14, 16],
];

console.log(zigZag(array)); // icons
console.log(zigZag(array_1)); // numbers

老答案

试试这个,我想这是你想做的。

let array = [
    [1, 3, 4, 10],
    [2, 5, 9, 11],
    [6, 8, 12, 15],
    [7, 13, 14, 16],
];

function mergeArray(array) {
    let merged = array.reduce((item, total) => [...total, ...item], []);
    return merged.sort((a, b) => a - b);
}

let result = mergeArray(array);

console.log(result)

【讨论】:

  • 但是这样做只是对数组进行升序排序,这里的挑战是按照 zig zag 方式对数组进行排序
  • @Alan 其实你的问题很好,但不知道为什么有人也对你投了反对票。
【解决方案3】:

我的理解是你要转换一个n×n数组如:

[ ['?', '?', '?', '?']

, ['?', '?', '?', '?']

, ['?', '?', '?', '?']

, ['?', '?', '?', '?'] ]

进入:

['?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?']

让我们将原始数组转换为“位置矩阵”,并尝试描绘“之字形”:

[ [[0,0], [0,1], [0,2], [0,3]]
// ↙      ↗      ↙      ↗
, [[1,0], [1,1], [1,2], [1,3]]
// ↗      ↙      ↗      ↙
, [[2,0], [2,1], [2,2], [2,3]]
// ↙      ↗      ↙      ↗
, [[3,0], [3,1], [3,2], [3,3]]
// ↗      ↙      ↗      ↙
]

如果我们专注于边缘,我们可以开始制定模式:

[ [0,0]
, [1,0], /* … */ [0,1]
, [2,0], /* … */ [0,2]
, [3,0], /* … */ [0,3]
, [3,1], /* … */ [1,3]
, [3,2], /* … */ [2,3]
,                [3,3] ]

现在我们需要计算出每条边之间的所有[x,y],并以相反的方向遍历每条边:

const inp1 = zigzag([ ['?', '?', '?', '?']

                    , ['?', '?', '?', '?']

                    , ['?', '☝️', '?', '?']

                    , ['?', '?', '?', '?'] ]);

const inp2 = zigzag([ ['?', '?', '?']

                    , ['?', '?', '?']

                    , ['?', '☝️', '?'] ]);

const inp3 = zigzag([ ['?', '?']

                    , ['?', '?'] ]);

const inp4 = zigzag([ ['?'] ]);

console.log(`
  [${String(inp1)}]
  [${String(inp2)}]
  [${String(inp3)}]
  [${String(inp4)}]
`);
<script>
const zigzag = inp => {
  const m = inp.length - 1;
  const edges = [];
  for (let x = 0; x <= m; x++) edges.push([x, 0]);
  for (let x = 1; x <= m; x++) edges.push([m, x]);
  return edges.flatMap(([x, y], i) => {
    const path = [[x, y]];
    for (let a = x, b = y; a != y && b != x;) path.push([--a, ++b]);
    return (i % 2 ? path : path.reverse()).map(([x, y]) => inp[x][y]);
  });
}
</script>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-16
    • 2014-04-21
    • 2015-10-18
    • 2011-02-04
    • 2014-12-26
    • 2016-09-04
    相关资源
    最近更新 更多