我想这是一个开放性的问题,不是一个完全具体的问题,但是我认为这是一个很好的例子,说明我们的大脑可以轻松地完成哪些工作,可能很难编写代码。一个解决方案很酷,但是我真的对您的未来方法更感兴趣。
这个特殊问题来自CodeSignal的图论部分,并要求我们编写一个函数,该函数根据给定的邻接矩阵(对于本示例而言不重要)来确定图是否类似于领结。
您可以想象一个中心顶点,其中有两对折断的“道路”(或度数),每对在其其他两个顶点之间共享一个排他的“道路”。
我已经解决了其他几个问题,但这是一组新的包含特定形状的问题,并且更容易发现传递输入的模式。我已经使用了大量的Array.prototype方法来构建和转换多维数组。 每个问题都花了我相当长的时间。我真的很难找到一种有效的方法来处理这些数据。
以下是测试用例的“道路”(或度数)列表。(为方便起见,我将邻接矩阵变成了道路阵列。)每个数字代表一个节点,或者一个顶点(如果容易的话,永远只有五个)...
[ [ '0', '1' ],
[ '0', '2' ],
[ '1', '0' ],
[ '1', '2' ],
[ '2', '0' ],
[ '2', '1' ],
[ '2', '3' ],
[ '2', '4' ],
[ '3', '2' ],
[ '3', '4' ],
[ '4', '2' ],
[ '4', '3' ] ]
(注意:中心顶点将不在数组中指定,这只是一个示例。)
即使没有图论训练,我们也可以在几秒钟内说出这是有效的“领结”。
注意:有些道路是重复的,但我是故意这样做的...我认为如果更容易看清,那么会更容易编码。
我们想从这样的数组中读取并确定(返回true)道路是否形成领结。 |> <|
我之所以问是因为我敢打赌,有一些我不知道要考虑的JavaScript功能。我知道地图和集合是什么,我认为地图可能会有所帮助,但是我有点缺乏编码经验。预先谢谢你!
答案 0 :(得分:0)
寻找有效地完成这类事情的算法可能非常棘手-我不一定能在那方面为您提供建议,但是我可以提供一些编码建议。
普通的JavaScript object
或Map
可能是图形对象的有用数据类型。它们实际上是相似的(略有不同)数据类型,它们根据键值对存储事物。一种策略:您可以将每个节点设置为键,将一组连接的节点设置为值。对于此信息,这感觉像是一个更有用的结构。像这样:
/**
* Convert array of arrays into object
* where {key=node, val=[array of connected nodes]}
*/
function arrayToObj(roadsArr) {
// start with empty object
var obj = {};
// iterate over each pair in roads array
// initialize new {key: [val]} entry if none exists
// otherwise add to existing list of values
roadsArr.forEach(function(pair) {
var key = pair[0];
var val = pair[1];
if (obj[key] === undefined) {
obj[key] = [val];
} else {
obj[key].push(val);
}
});
return obj;
}
roadsArr = [
["0", "1"],
["0", "2"],
["1", "0"],
["1", "2"],
["2", "0"],
["2", "1"],
["2", "3"],
["2", "4"],
["3", "2"],
["3", "4"],
["4", "2"],
["4", "3"]
];
var roadsObj = arrayToObj(roadsArr);
console.log(roadsObj);
接下来,我会考虑需要检查的条件,以验证是否为领结并一次对其进行测试。
您提到应该恰好有五个节点:我们可以通过检查正好有五个键来对其进行测试。
/**
* Check there are exactly five nodes
* Returns true if 5 keys in roadsObj, false otherwise
*/
function hasFiveNodes(roadsObj) {
var keys = Object.keys(roadsObj); // -> [0, 1, 2, 3, 4]
return keys.length === 5;
}
您提到一个节点应具有四个连接,而其他节点则应具有两个连接。这是一种检查方法:
/**
* Check that each node has two connections, except one node with 4
*/
function hasValidNumConnections(roadsObj) {
// extract array of values from object
var valuesArr = Object.values(roadsObj); // -> [[0,1], [0,2] ... [2,3]]
// map list of values into list of lengths
var lenArr = valuesArr.map(x => x.length); // -> [2, 2, 4, 2, 2]
// sort array of lengths
var sortedLenArr = lenArr.sort(); // -> [2, 2, 2, 2, 4]
// compare to desired string (because comparing arrays is tricky in JS)
return sortedLenArr.toString() === "2,2,2,2,4";
}
您可能还必须检查其他一些条件-例如,您可能不仅要检查每个节点有多少连接,还要检查哪些连接以确保领结结构。 / p>
将每个条件检查分离为自己的功能可能不是最有效的策略,但是如果效率不是至关重要的,则它提供了一个很好的结构来思考问题并继续构建您的解决方案。总之,它看起来可能像这样:
// ---------- helper function ----------
/**
* Convert array of arrays into object
* where {key=node, val=[array of connected nodes]}
*/
function arrayToObj(roadsArr) {
var obj = {};
roadsArr.forEach(function(pair) {
var key = pair[0];
var val = pair[1];
if (obj[key] === undefined) {
obj[key] = [val];
} else {
obj[key].push(val);
}
});
return obj;
}
// ---------- validator functions ----------
/**
* Check there are exactly five nodes
* Returns true if 5 keys in roadsObj, false otherwise
*/
function hasFiveNodes(roadsObj) {
var keys = Object.keys(roadsObj); // -> [0, 1, 2, 3, 4]
return keys.length === 5;
}
/**
* Check that each node has two connections, except one node with 4
*/
function hasValidNumConnections(roadsObj) {
var valuesArr = Object.values(roadsObj); // -> [[0,1], [0,2] ... [2,3]]
var lenArr = valuesArr.map(x => x.length);
var sortedLenArr = lenArr.sort();
return sortedLenArr.toString() === "2,2,2,2,4";
}
// ---------- main function ----------
/**
* Check if given array represents a bowtie graph.
*/
function isBowtie(roadsArr) {
// convert array to object
var roadsObj = arrayToObj(roadsArr);
// has exactly 5 nodes?
if (!hasFiveNodes(roadsObj)) {
return false;
}
console.log("> has 5 nodes");
// has one node with 4 connections
if (!hasValidNumConnections(roadsObj)) {
return false;
}
console.log("> has valid number connections");
// other checks??
// ... insert here
// if all pass, return true
return true;
}
// ---------- testing ----------
roadsArr = [
["0", "1"],
["0", "2"],
["1", "0"],
["1", "2"],
["2", "0"],
["2", "1"],
["2", "3"],
["2", "4"],
["3", "2"],
["3", "4"],
["4", "2"],
["4", "3"]
];
var result = isBowtie(roadsArr);
console.log(result);