我的拓扑排序有什么问题

时间:2017-01-27 06:19:54

标签: javascript arrays sorting

var input = ["KittenService: ", "Leetmeme: Cyberportal", "Cyberportal: Ice", "CamelCaser: KittenService", "Fraudstream: Leetmeme", "Ice: "];

var output = [];

function valid(input) {
  for (var i = 0; i < input.length; i++) {
    var array = input[i].trim().split(':');
    var packageName = array[0].trim();
    var dependencyName = array[1].trim();
    if (array.length > 1 && dependencyName === '') {

      if (output.indexOf(packageName) === -1) {
        output.push(packageName);
      } else {
        return;
      }
    } else if (array.length > 1 && dependencyName !== '') {
      if (output.indexOf(dependencyName) === -1) {
        output.push(dependencyName);
        if (output.indexOf(dependencyName) > -1) {
          if (output.indexOf(packageName) > -1) {
            continue;
          } else {
            output.push(packageName);
          }
        }
      } else if (output.indexOf(dependencyName) > -1) {
        output.push(packageName);
      }
    }
  }
  return output.join(', ');
}
valid(input);

console.log(output);

我想找到一种获得以下输出的方法:

  

“KittenService,Ice,Cyber​​portal,Leetmeme,CamelCaser,Fraudstream”

现在它记录:

  

'KittenService,Cyber​​portal,Leetmeme,Ice,CamelCaser,Fraudstream'

我听说拓扑排序可以解决这个问题,但我不确定如何实现tsort。我怎么能这样做,或者我可以使用其他方法来解决这个问题?我想在没有额外库的情况下这样做。

1 个答案:

答案 0 :(得分:0)

一些问题:

  1. 代码中的第二个push未验证推送的项是否具有某些依赖项。例如,推送依赖项Cyberportal,但是您没有检查是否存在Cyberportal本身具有依赖关系的对:它有...通常,这可能也会重复你可能会发现的依赖:也可以有另一个依赖。所以你需要一个迭代或递归的解决方案。

  2. 第一个return后的else错误。在某些情况下,这会使您的输出不完整。尝试使用相同输入的代码,然后"CamelCaser: KittenService"移动到输入数组的开头。由于这个错误,你只会在输出中得到两个元素。

  3. 在推送之后检查推送的元素是否在数组中是没用的。你不需要先if (output.indexOf(dependencyName) > -1):它永远都是真的。

  4. if (output.indexOf(dependencyName) > -1)的另一次出现也没用,因为它也一直都是真的。

  5. 当您将方法(array.length > 1)应用于第二个元素时,检查trim()是没用的。

  6. 您不应该让函数将其结果放在全局变量中。而是将output创建为函数的局部变量,并返回该变量(不是.join()结果)。

  7. 即使进行了更正,该算法也没有线性时间复杂度,因为在一个也是<的循环中有indexOf O(n)) em> O(n),导致 O(n²)时间复杂度。然而,这可以在线性时间内完成。

  8. 解决方案

    我假设某个值只依赖于最多一个其他元素 - 不计算通过该单个依赖项的间接依赖性 - 因为你的符号(带冒号)似乎暗示了这一点。

    我的建议是使用哈希表,使用SetMap来提供对其元素的持续访问。其次,通过递归,您可以确保在输出元素本身之前首先输出元素的依赖关系。

    这是ES6代码:

    function valid(input) {
        let result = new Set(),
            pairs = new Map(input.map(s => s.split(': '))),
            loop = (_, key) => { // Recursive function to add key with dependencies
                if (pairs.get(key)) { // Has dependency
                    loop(_, pairs.get(key)); // Recurse to add dependencies first 
                    pairs.set(key, null); // Clear dependency
                }
                // After dependencies were added, now add this key
                result.add(key); // Duplicates are ignored
            };
        pairs.forEach(loop); // Call loop for every element
        return [...result]; // Convert Set to Array: order is kept
    }
    
    // Sample run:
    var input = ["KittenService: ", "Leetmeme: Cyberportal", "Cyberportal: Ice",
                 "CamelCaser: KittenService", "Fraudstream: Leetmeme", "Ice: "];
    var result = valid(input);
    console.log(result);

    如果您没有ES6支持,则可以使用普通对象而不是“设置”和“地图”。并使用普通function s而不是箭头符号。