【问题标题】:Maximum subsets of intervals that does not exceed coverage limit?不超过覆盖范围限制的最大间隔子集?
【发布时间】:2017-12-24 16:13:19
【问题描述】:

这是我很困惑的一个编码问题。

给定一个二维数组[[1, 9], [2, 8], [2, 5], [3, 4], [6, 7], [6, 8]],每个内部数组代表一个区间;如果我们把这些间隔堆积起来,我们会看到:

1 2 3 4 5 6 7 8 9
  2 3 4 5 6 7 8
  2 3 4 5 
    3 4   
          6 7
          6 7 8

现在有一个限制,每个位置的覆盖率应该

那么问题是:最多可以选择多少个区间子集,以便每个区间可以满足

我应该对这样的问题应用什么算法?我想这是间隔调度的变体问题?

谢谢

【问题讨论】:

  • 明确地说:您正在寻找满足“覆盖率
  • 对于您的所有问题,答案是:是的;你所有的理解正是我的意思。谢谢!

标签: algorithm intervals


【解决方案1】:

我希望我已经正确理解了这个问题。这是我可以使用 C# 获得的解决方案:

                //test
                int[][] grid =  { new int[]{ 1, 9 }, new int[] { 2, 8 }, new int[] { 2, 5 }, new int[] { 3, 4 }, new int[] { 6, 7 }, new int[] { 6, 8 } };
                SubsetFinder sf = new SubsetFinder(grid);
                int t1 = sf.GetNumberOfIntervals(1);//6
                int t2 = sf.GetNumberOfIntervals(2);//5
                int t3 = sf.GetNumberOfIntervals(3);//5
                int t4 = sf.GetNumberOfIntervals(4);//2
                int t5 = sf.GetNumberOfIntervals(5);//0


        class SubsetFinder
        {
            Dictionary<int, List<int>> dic;
            int intervalCount;
            public SubsetFinder(int[][] grid)
            {
                init(grid);
            }
            private void init(int[][] grid)
            {
                this.dic = new Dictionary<int, List<int>>();
                this.intervalCount = grid.Length;
                for (int r = 0; r < grid.Length; r++)
                {
                    int[] row = grid[r];
                    if (row.Length != 2) throw new Exception("not grid");
                    int start = row[0];
                    int end = row[1];
                    if (end < start) throw new Exception("bad interval");
                    for (int i = start; i <= end; i++)
                        if (!dic.ContainsKey(i))
                            dic.Add(i, new List<int>(new int[] { r }));
                        else
                            dic[i].Add(r);
                }
            }
            public int GetNumberOfIntervals(int coverageLimit)
            {
                HashSet<int> hsExclude = new HashSet<int>();
                foreach (int key in dic.Keys)
                {
                    List<int> lst = dic[key];
                    if (lst.Count < coverageLimit)
                        foreach (int i in lst)
                            hsExclude.Add(i);
                }
                return intervalCount - hsExclude.Count;
            }
        }

【讨论】:

    【解决方案2】:

    我认为您可以使用扫描算法来解决这个问题。这是我的方法:

    一般的想法是,我们不是找出您可以选择并且仍然符合限制的最大间隔数,而是找出必须删除的最小间隔数,以使所有数字符合限制。我们可以这样做:

    首先创建一个三元组向量,第一部分是整数,第二部分是布尔值,而第三部分是整数。第一部分表示输入中的所有数字(区间的startend),第二部分告诉我们第一部分是区间的开始还是结束,而第三部分表示@ 987654323@的区间。

    根据第一部分对创建的向量进行排序,如果出现平局,则start应位于某些区间的end之前。

    在您提供的示例中,向量将是:

    1,0,@@2,0,@@2,02,0,@@@@3,0,@9876543331 , 9,1

    现在,遍历向量,同时保留一组整数,表示当前采用的间隔。集合内的数字代表当前采用的间隔的ends。该集合应保持按升序排序。

    在遍历向量时,我们可能会遇到以下两种可能性之一:

    1. 我们目前正在处理间隔的start。在这种情况下,我们只需将这个区间的end(由第三部分id标识)添加到集合中。如果集合的大小超过限制,我们肯定要删除一个区间,但是哪个区间最适合删除呢?当然,这是end 最大的区间,因为删除此区间不仅可以帮助您减少所采用的区间数以适应限制,而且由于它持续时间最长,因此在将来也会很有帮助。只需从集合中删除此区间(对应的end 将在集合中的最后一个,因为集合按end 的升序排序)

    2. 我们目前正在处理间隔的end,在这种情况下检查集合。如果它包含指定的end,只需删除它,因为相应的间隔已经结束。如果集合不包含与我们正在处理的元素匹配的end,只需继续迭代到下一个元素,因为这意味着我们已经决定不采用相应的间隔。

    如果您需要计算所用间隔的数量,甚至打印它们,都可以轻松完成。每当你处理一个区间的end,并且你实际上在集合中找到了这个end,这意味着相应的区间是一个已取的,你可以将你的答案加一,打印它或将它保存在一些代表你的答案的向量。

    我的方法的总复杂度是:N Log(N),其中 N 是输入中给出的区间数。

    【讨论】:

      猜你喜欢
      • 2017-08-02
      • 1970-01-01
      • 2017-03-29
      • 2018-02-10
      • 1970-01-01
      • 2016-08-15
      • 1970-01-01
      • 1970-01-01
      • 2010-10-31
      相关资源
      最近更新 更多