了解餐桌上最佳座位算法的问题

时间:2019-02-03 23:44:11

标签: javascript algorithm data-structures

我正在阅读一个问题,并试图解决这个问题。

  

您已邀请N个人共进晚餐。假设4。

     

您有一个圆形的餐桌,想让每个人都坐下   它。不幸的是,并不是所有的朋友都是彼此的朋友   其他,但您想让每个人都享有最佳座位   人们尽可能地坐在他们认为是朋友的人旁边,   不是敌人。

     

您已按照大小矩阵绘制了每个人的友谊和仇恨   NxN并以整数1表示友谊,以-1表示仇恨,   和零的冷漠。

[[ 0, 1, 1, 1, 1],    ← yes you like all your friends
 [-1, 0, 1,-1, 0],
 [-1, 1, 0, 1, 0],
 [ 1, 1, 1, 0,-1],
 [ 1, 0, 0,-1, 0]]

问题:

  

->编写Javascript方法,将最佳座位安排计算为Array,例如对于给定的输入矩阵,[0,4,2,1,3]。 (假设索引为0   和N-1相邻放置)。时间的复杂度是多少   解?添加关于可能的优化的想法。

我尝试手动解决此问题,但是我不了解给定输入矩阵的问题示例[0,4,2,1,3]。

有人可以启发我吗?

他/她是怎么想出[0,4,2,1,3]?

非常感谢您的宝贵时间。

2 个答案:

答案 0 :(得分:5)

  

他/她是怎么想出[0,4,2,1,3]?

对于示例输入来说,这种排列当然不是正确的答案(请参见下面的推理),因此我认为上面的Emma注释是不切实际的:问题陈述只是说明“ “作为数组排列”应该看起来像 ,而不是具体说明示例输入的最优座位布置。


至于为什么我说[0,4,2,1,3]当然不是您所举示例的正确答案。 。 。我不完全了解我们如何确定一个排列是否比另一个排列更好,但是很明显,[0,4,1,2,3]在任何方面都更好。对于[0,4,2,1,3]和[0,4,1,2,3],第一人称(0)都喜欢两个邻居。第二个人(4)对两个邻居都保持中立;第三和第五个人(前者为2和3,后者为1和3)都喜欢一个邻居,彼此之间保持中立。这两个排列之间的唯一区别在于,在[0,4,2,1,3]中,第四人称(1)对一个邻居是中性的,而不喜欢是另一个,而在[0, 4,1,2,3],第四个人(2)对一个邻居是中立的,而喜欢是另一个。因此,无论我们认为增加喜欢或减少不喜欢更为重要,后者显然是优越的。

答案 1 :(得分:5)

检查所有可能的顺序是经典的排列任务,即使针对此特定问题可能有更有效的算法。

一种优化可以通过将排列长度减少为数组长度1来完成,因为以循环顺序排列,例如0,1,2,3,4和4,0,1,2,3(以及所有其他旋转)是相同的。您可以始终从位置0开始在自己的座位上查看订单。

def sort():
    f = open("source.txt","r")
    w = open("result.txt","a+")
    word = ''
    og_lines = sum(1 for line in open('source.txt'))
    print("Sorting",og_lines,"words...")
    new_lines = 1
    lenght = 0
    word = f.readline(new_lines)
    new_lines+=1
    buffer=f.readline(new_lines)
    while (buffer != ''):
        if (len(buffer)>len(word)):
            word=buffer
            print("change")
        new_lines+=1
        print(new_lines, "lines read")
        buffer=f.readline(new_lines)
        buffer.rstrip()
    lenght = len(word.rstrip())
    print("Longest word is",word.rstrip(),lenght)

输出:

(function ()
{
  'use strict';

  let popularity =
  [
    [ 0, 1, 1, 1, 1],   // ← yes you like all your friends
    [-1, 0, 1,-1, 0],
    [-1, 1, 0, 1, 0],
    [ 1, 1, 1, 0,-1],
    [ 1, 0, 0,-1, 0],
  ];

  function permutation(arr)
  {
    let
      l = arr.length,
      perms = []
    ;

    if(l<2)
      return [arr];

    for(let i=0; i<l; i++)
    {
      let
        cpy    = Array.from(arr),
        [perm] = cpy.splice(i, 1)
      ;
      perms.push(...permutation(cpy).map(v => [perm, ...v]));
    }

    return perms;
  }


  let
    keys = Array.from(popularity.keys()).slice(1),
    permutations = permutation(keys),
    rating = permutations.map(v =>
    {
      let
        last = v.length -1,

        // start with our own relationships to the left and right neighbour
        // (each: we like him, he likes us)
        rate =
            popularity [0]       [v[0]]
          + popularity [v[0]]    [0]
          + popularity [0]       [v[last]]
          + popularity [v[last]] [0]
      ;

      for(let i = 0; i<last; i++)
        rate += popularity[v[i]][v[i+1]] + popularity[v[i+1]][v[i]];

      return [rate, [0, ...v]];
    }
  ).sort( (v1, v2) => ( v1[0] === v2[0] ? 0 : (v1[0] > v2[0] ? -1 : 1))  );

  console.log(rating);

})();

正如我们所看到的,仍然存在反向排列,而您自己(0)的组合当然具有相同的评分。消除镜像顺序(即反向排列)将是另一种优化。

我这样做是为了一步一步地进行演示,以使逐步理解单个问题的代码更具可读性。您可以将评分计算直接重构为置换算法。

正确计算时间复杂度似乎并不那么容易。请阅读下面评论中的讨论。