从起始节点查找分隔值

时间:2016-07-23 12:59:12

标签: javascript

我在一些在线编码练习中发现,这个看起来非常酷,我想试一试。

问题陈述

奎因是一个非常受欢迎,非常谦虚的家伙。其他学生在称为QDist的单元中衡量他们的受欢迎程度。

可以通过找出他们自己和奎因之间的分离程度来计算他们的QDist值。例如: 如果Quinn是Dave的朋友,而Dave是Travis的朋友,那么Dave的QDist值是1,而Travis是2。

输出

为每个人输入的名称QDist按名称按字母顺序排序。 如果一个人无论如何都没有连接到Quinn,输出名称为uncool

给定友谊列表,按字母顺序列出每个人及其QDist值。

示例输入/输出

10
Alden Toshiko
Che Kortney
Che Dorian
Ronda Lindell
Sharon Alden 
Dorian Quinn
Owen Sydnee
Alden Che
Dorian Tyra
Quinn Ally

输出

Alden 3
Che 2
Dorian 1
Kortney 3
Lindell uncool
Ally 1
Owen uncool
Quinn 0
Ronda uncool
Sharon 4
Sydnee uncool
Toshiko 4
Tyra 2

我的方法

首先,我不想要答案我只是想要一个关于如何在javascript中解决问题的提示或指导(因为它是我最熟悉的语言)。我的想法是将程序分解为一个对象和数组,并尝试在每个名称之间创建一个族关系,作为嵌套对象或者数组。然后我可以使用某种递归来查找数组或对象的深度。

最好的方法是什么?

3 个答案:

答案 0 :(得分:1)

如果我必须解决这个问题,

首先,我会创建一个数组并通过查找行(元素) studentX ←→ Quinn 与Quinn 1 的学生初始化它在原始阵列中。

然后我会通过查找行 studentX ←→学生(n-1)FromQuinn <以递归方式搜索那些具有quinn水平 n 的人/ p>

答案 1 :(得分:1)

您可以根据输入创建人员列表。它可以是一个对象,其中每个键是一个人的名字,相应的值是一个名字数组,代表该人的朋友。当然你应该确保当你把B添加为A的朋友时,你还必须添加A作为B的朋友。

对于示例输入,上面的结构如下所示:

{
  "Alden": ["Toshiko","Sharon","Che"],
  "Toshiko": ["Alden"],
  "Che": ["Kortney","Dorian","Alden"],
  "Kortney": ["Che"],
  "Dorian": ["Che","Quinn","Tyra"],
  "Ronda": ["Lindell"],
  "Lindell": ["Ronda"],
  "Sharon": ["Alden"],
  "Quinn": ["Dorian","Ally"],
  "Owen": ["Sydnee"],
  "Sydnee": ["Owen"],
  "Tyra": ["Dorian"],
  "Ally": ["Quinn"]
}

然后跟踪一个名单列表,从Quinn开始,以及从0开始的距离。

然后,对于该列表中的每个名称,将当前距离指定为其QDist值。然后找到他们的朋友,把他们放在一起。删除已收到QDist值的名称。

然后增加距离,并对新名称列表重复上述步骤。

不断重复,直至名称列表为空。

请注意,如果您按正确的顺序执行操作,则可以使用QDist值替换朋友的人员列表。因此,在前两次迭代之后,上述结构将发生变化:

{
  "Alden": ["Toshiko","Sharon","Che"],
  "Toshiko": ["Alden"],
  "Che": ["Kortney","Dorian","Alden"],
  "Kortney": ["Che"],
  "Dorian": 1,
  "Ronda": ["Lindell"],
  "Lindell": ["Ronda"],
  "Sharon": ["Alden"],
  "Quinn": 0,
  "Owen": ["Sydnee"],
  "Sydnee": ["Owen"],
  "Tyra": ["Dorian"],
  "Ally": 1
}

算法完成后,您有:

{
  "Alden": 3,
  "Toshiko": 4,
  "Che": 2,
  "Kortney": 3,
  "Dorian": 1,
  "Ronda": ["Lindell"],
  "Lindell": ["Ronda"],
  "Sharon": 4,
  "Quinn": 0,
  "Owen": ["Sydnee"],
  "Sydnee": ["Owen"],
  "Tyra": 2,
  "Ally": 1
}

现在剩余的朋友阵列需要用“uncool”替换,因为显然相应的人与Quinn没有关系。列表也需要排序。

扰流板警告!

这是一个工作片段:

// Get input as text
var input = `10
Alden Toshiko
Che Kortney
Che Dorian
Ronda Lindell
Sharon Alden 
Dorian Quinn
Owen Sydnee
Alden Che
Dorian Tyra
Quinn Ally`;

// Build persons list with friends list
var persons = 
    // Take the input string
    input
    // Split it by any white-space to get array of words
    .split(/\s+/)
    // Skip the word at position 0: we don't need the line count
    .slice(1)
    // Loop over that array and build an object from it 
    .reduce(
        // Arguments: obj = result from previous iteration
        //            name = current name in names array
        //            i = index in that array
        //            names = the whole array being looped over
        (obj, name, i, names) => (
               // Get the list of friends we already collected for this name.
               // Create it as an empty array if not yet present.
               obj[name] = (obj[name] || [])
               // Add to that list the previous/next name, depending
               // whether we are at an odd or even position in the names array
               .concat([names[i%2 ? i-1 : i+1]])
               // Use the updated object as return value for this iteration
               , obj)
        // Start the above loop with an empty object
        , {});

// Now we have a nice object structure: 
//    { [name1]: [friendName1,friendName2,...], [name2]: ... }
// Start with Quinn as the only person we currently look at.
var friends = ['Quinn'];
// Increment the distance for each "generation" of friends 
// until there are none left.
for (var i = 0; friends.length; i++) {
    // Replace the friends list with a new list, 
    // while giving the friends in the current list a distance
    friends = 
        // Start with the current list of friends
        friends
        // Loop over these friends. 
        // Only keep those that still have a friends array (object) assigned to them,
        // since the others were already assigned a distance number.
        .filter(friend => typeof persons[friend] === "object")
        // Loop over those friends again, building a new list of friends
        .reduce((friends, friend, k) => [
                // Add this friends' friends to the new list
                friends.concat(persons[friend]),
                // ... and then replace this friends' friend list 
                // by the current distance we are at.
                persons[friend] = i
                // Return the first of the above two results (the new list)
                // for the next iteration.
                ][0]
            // Start with an empty array for the new friends list
            , []);
}

// Now we have for each person that connects to Quinn a number: 
//    { [name1]: number, ... }

// Convert this to a format suitable to output
var result = 
    // Get list of names from the object (they are the keys)
    Object.keys(persons)
    // Sort that list of names
    .sort()
    // Loop over these names to format them
    .map(name =>
        // Format as "name: distance" or "name: uncool" depending on whether there
        // still is an array of friends (object) in this entry
        name + ': ' + (typeof persons[name] == 'object' ? 'uncool' : persons[name]));

// Output the result in the console
console.log(result);

更详细,但更容易理解的版本:

// Get input as text
var input = `10
Alden Toshiko
Che Kortney
Che Dorian
Ronda Lindell
Sharon Alden 
Dorian Quinn
Owen Sydnee
Alden Che
Dorian Tyra
Quinn Ally`;

// Build persons list with friends list
// Take the input string
var persons = input;
// Split it by any white-space to get array of words
persons = persons.split(/\s+/)
// Skip the word at position 0: we don't need the line count
persons = persons.slice(1)
// Loop over that array and build an object from it 
var obj = {}; // Start loop with an empty object
for (var i = 0; i < persons.length; i++) {
    var name = persons[i]; // name = current name in names array
    // Get the list of friends we already collected for this name.
    // Create it as an empty array if not yet present.
    if (obj[name] === undefined) obj[name] = [];
    // Add to that list the previous/next name, depending
    // whether we are at an odd or even position in the names array
    obj[name].push(persons[i%2 === 1 ? i-1 : i+1]);
}
// Assign result to persons
persons = obj;
// Now we have a nice object structure: 
//    { [name1]: [friendName1,friendName2,...], [name2]: ... }
// Start with Quinn as the only person we currently look at.
var friends = ['Quinn'];
// Increment the distance for each "generation" of friends 
// until there are none left.
for (var i = 0; friends.length !== 0; i++) {
    // Loop over those friends, building a new list of friends
    // Start with an empty array for the new friends list
    var newFriends = [];
    for (var k = 0; k < friends.length; k++) {
        var friend = friends[k];
        // Only consider those that still have a friends array (object) assigned to them,
        // since the others were already assigned a distance number.
        if (typeof persons[friend] === "object") {
            // Add this friends' friends to the new list
            newFriends = newFriends.concat(persons[friend]);
            // ... and then replace this friends' friend list 
            // by the current distance we are at.
            persons[friend] = i;
        }
    };
    // Make the new list the current list:
    friends = newFriends;
}

// Now we have for each person that connects to Quinn a number: 
//    { [name1]: number, ... }

// Convert this to a format suitable to output
// Get list of names from the object (they are the keys)
var result = Object.keys(persons);
// Sort that list of names
result.sort();
// Loop over these names to format them
for (var i = 0; i < result.length; i++) {
    var name = result[i];
    // Format as "name: distance" or "name: uncool" depending on whether there
    // still is an array of friends (object) in this entry
    if (typeof persons[name] == 'object') {
        result[i] = name + ': uncool';
    } else {
        result[i] = name + ': ' + persons[name];
    }
}

// Output the result in the console
console.log(result);

答案 2 :(得分:0)

我试图理解

var persons = input.split(/\s+/).slice(1).reduce(function(obj,name,i,names){
    return (obj[name] = (obj[name] || []).concat([names[i%2 ? i-1 : i+1]]), obj);

},{});

首先input.split(/\s+/).slice(1)为我们提供一个包含其中所有名称的数组。 现在

(obj[name] = (obj[name] || []).concat([names[i%2 ? i-1 : i+1]]), obj);
根据reduce方法属性,

obj默认设置为{}

name是当前值,基本上从Alden一直到Allyi将从1-10开始,names是数组

现在我们说obj[name] = obj[name].concat([names[i%2 ? i-1 : i+1]]),obj);如果这是可能的话。如果无法设置obj[name] = [].concat([names[i%2 ? i-1 : i+1]]),obj);。这是我在阅读||

时的解释

迭代示例

首先obj = {},名称为Alden 所以Alden类型,persons = { Alden: ..}将是obj[Alden].concat(names[2],obj),它将是2,因为1 mod 2无法达到。

现在我有点困惑...... ,obj到底在做什么......?我正在解释这个吗?