Algorithm 谷歌算法访谈

Algorithm 谷歌算法访谈,algorithm,Algorithm,我是一个长期潜伏者,刚刚接受了谷歌的采访,他们问了我这个问题: 不同的艺术家想在皇家阿尔伯特大厅表演,你负责安排 他们的音乐会。在大厅演出的要求以先到先得的方式处理 政策。每天只能有一场演出,而且不能有任何音乐会 相互之间在5天内发生 给定不可能的请求时间d(即,在已安排的5天内- uled性能),给出一个O(logn)时间算法来查找下一个可用的日期d2 (d2>d) 我不知道如何解决它,现在面试结束了,我急切地想知道如何解决它。知道你们大多数人有多聪明,我想知道你们是否能帮我一把。这不是家庭作

我是一个长期潜伏者,刚刚接受了谷歌的采访,他们问了我这个问题:

不同的艺术家想在皇家阿尔伯特大厅表演,你负责安排 他们的音乐会。在大厅演出的要求以先到先得的方式处理 政策。每天只能有一场演出,而且不能有任何音乐会 相互之间在5天内发生

给定不可能的请求时间d(即,在已安排的5天内- uled性能),给出一个O(logn)时间算法来查找下一个可用的日期d2 (d2>d)


我不知道如何解决它,现在面试结束了,我急切地想知道如何解决它。知道你们大多数人有多聪明,我想知道你们是否能帮我一把。这不是家庭作业,或任何类似的东西。我只是想学习如何解决这个问题,以便将来面试时使用。我试着问后续问题,但他说我只能告诉你这些。

将预定的音乐会存储在一个文件夹中,并通过二进制搜索找到可行的解决方案

大概是这样的:

FindDateAfter(tree, x):
  n = tree.root
  if n.date < x 
    n = FindDateAfter(n.right, x)
  else if n.date > x and n.left.date < x
    return n
  return FindDateAfter(n.left, x)

FindGoodDay(tree, x):
  n = FindDateAfter(tree, x)
  while (n.date + 10 < n.right.date)
    n = FindDateAfter(n, n.date + 5)
  return n.date + 5
FindDateAfter(树,x):
n=tree.root
如果n.datex,n.left.date
您需要一个包含可用日期间隔的普通二进制搜索树。只需搜索包含d的区间。如果不存在,则按顺序取下一个搜索停止点的间隔

注意:相邻间隔必须在单个节点中融合在一起。例如:可用的日期间隔{2-15}和{16-23}应该变成{2-23}。如果取消音乐会预订,可能会发生这种情况


或者,如果连续的不可用时间间隔融合在一起,则可以使用不可用日期树。

存储每年、每季度和每月使用的夜数。要想找到一个免费的夜晚,先找第一年没有预订满的,然后是该年内的季度,然后是月份。然后检查该月的每个夜晚


日历系统中的不规则性使得这有点棘手,因此您可以将4晚作为“月”,16晚作为“季度”等单位,而不是使用年和月。为什么不尝试使用Union Find?您可以将每个音乐会日+接下来的5天作为一组的一部分进行分组,然后在给定的日期执行查找,返回下一组ID,这将是您的下一个音乐会日期


如果使用树来实现,则会产生O(logn)时间复杂度。

假设在级别1,所有计划细节都可用。
public static int FindConcertTime(TreeNode<Tuple<int, int>> node, int reqDay)
{
    // Not found!
    if (node == null)
    {
        return -1;
    }
    Tuple<int, int> currRange = node.Value;
    // Found range.
    if (currRange.Item1 <= reqDay &&
        currRange.Item2 >= reqDay)
    {
        // Return requested day.
        return reqDay;
    }
    // Go left.
    else if (currRange.Item1 > reqDay)
    {
        int suggestedDay = FindConcertTime(node.Left, reqDay);
        // Didn't find appropriate range in left nodes, or found day
        // is further than current option.
        if (suggestedDay == -1 || suggestedDay > currRange.Item1)
        {
            // Return current option.
            return currRange.Item1;
        }
        else
        {
            // Return suggested day.
            return suggestedDay;
        }
    }
    // Go right.
    // Will always find because the right-most node has "int.MaxValue" as Item2.
    else //if (currRange.Item2 < reqDay)
    {
        return FindConcertTime(node.Right, reqDay);
    }
}
第2级16天的团体计划。 第16组第2级状态为第3级。 第16组第3级状态为第4级。 根据要扩展的天数,增加级别

现在从更高的级别进行搜索,并在最后进行二进制搜索。

系统复杂性:- 这意味着运行时随着输入的增长而变化。 假设我们有一个输入字符串“abcd”。这里我们遍历每个字符以找到其长度,因此所用的时间与字符串中的字符数成正比,就像n个字符一样。因此O(n)。 但是如果我们把字符串“abcd”的长度放在一个变量中,那么不管字符串有多长,我们仍然可以通过查看变量len来找到字符串的长度。(len=4)。 例:返回23。无论您输入的是什么,我们的输出仍然是23。 因此,复杂性为O(1)。因此,th程序将以恒定时间wrt输入大小运行。 对于O(logn)-操作以对数步进行

观察上面链接中的图像。在这里我们可以看到弯曲的线(对数线)。在这里,我们可以说,对于较小的输入,O(logn)表示法效果良好,因为我们可以在弯曲线中看到,所花费的时间较少,但当输入增加时,线性表示法即O(n)被认为是更好的方法。 还有最好和最坏的情况。就像上面的例子


你也可以在算法中引用这个技巧:

上面已经提到过,但是基本上用二叉树保持简单。你知道二叉树有对数N的复杂性。所以您已经知道需要使用什么算法。 您所要做的就是找到一个树节点结构,并使用二叉树插入算法来查找下一个可用日期: 一个可能的例子: 树节点有两个属性:d(音乐会的日期)和d+5(5天阻塞期的结束日期)。同样为了保持简单,请为这两个日期属性使用时间戳。
现在,在初始条件为root=null的情况下,使用二叉树顺序插入算法查找下一个可用日期是很简单的。

我使用了一个二叉搜索树(BST),它保存了可安排执行的有效空闲日的范围。 其中一个范围必须以int.MaxValue结尾,因为我们有无限的天数,所以它不能被绑定

下面的代码搜索距离请求日期最近的日期,并返回该日期

当H为树高时,时间复杂度为O(H)(通常H=log(N),但在某些情况下可能变成H=N)。 空间复杂度与时间复杂度相同

public static int FindConcertTime(TreeNode<Tuple<int, int>> node, int reqDay)
{
    // Not found!
    if (node == null)
    {
        return -1;
    }
    Tuple<int, int> currRange = node.Value;
    // Found range.
    if (currRange.Item1 <= reqDay &&
        currRange.Item2 >= reqDay)
    {
        // Return requested day.
        return reqDay;
    }
    // Go left.
    else if (currRange.Item1 > reqDay)
    {
        int suggestedDay = FindConcertTime(node.Left, reqDay);
        // Didn't find appropriate range in left nodes, or found day
        // is further than current option.
        if (suggestedDay == -1 || suggestedDay > currRange.Item1)
        {
            // Return current option.
            return currRange.Item1;
        }
        else
        {
            // Return suggested day.
            return suggestedDay;
        }
    }
    // Go right.
    // Will always find because the right-most node has "int.MaxValue" as Item2.
    else //if (currRange.Item2 < reqDay)
    {
        return FindConcertTime(node.Right, reqDay);
    }
}
公共静态int-FindConcertTime(TreeNode节点,int-reqDay)
{
//没有找到!
if(node==null)
{
返回-1;
}
元组currRange=node.Value;
//找到了射程。
如果(currRange.Item1=reqDay)
{
//返回请求的日期。
返回日期;
}
//向左走。
否则如果(currRange.Item1>reqDay)
{
int suggestedDay=findContentTime(node.Left,reqDay);
//在左侧节点中找不到合适的范围,或找到日期
//比