这是一个我很困惑的编码问题。
给定一个二维数组[[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
现在有一个限制,即每个职位的覆盖率应<= 3;显然我们可以看到位置3,4,6,7,覆盖范围是4.
然后问题是:最多可以选择多少个间隔子集,以便每个间隔可以符合&lt; = 3限制?很明显,对于这种情况,我们只需删除最长的间隔[1,9],因此最大子集数为6 - 1 = 5.
我应该对这样的问题应用什么算法?我猜这是区间调度的变体问题?
由于
答案 0 :(得分: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;
}
}
答案 1 :(得分:1)
我认为您可以使用扫描算法解决此问题。这是我的方法:
一般的想法是,我们会找到必须删除的最小间隔数,以便使所有数字都符合限制,而不是找出您可以选择并且仍然符合限制的最大间隔数。以下是我们如何做到这一点:
首先创建三元组的向量,第一部分是整数,第二部分是布尔值,第三部分是整数。第一部分表示输入中的所有数字(区间的start
和end
),第二部分表示第一部分是区间的开始还是结束,而第三部分part表示间隔的id
。
根据第一部分对创建的矢量进行排序,如果出现平局,start
应该在某些时间间隔的end
之前。
在您提供的示例中,向量将为:
1,0
,2,0
,2,0
,2,0
,3,0
,4,1
,5,1
,6.0
,6.0
,7,1
,8,1
,8,1
,9,1
现在,迭代向量,同时保留一组整数,表示当前采用的间隔。集合中的数字代表当前采用的间隔的ends
。该组应按升序排列。
在迭代向量时,我们可能会遇到以下两种可能之一:
我们目前正在处理间隔的start
。在这种情况下,我们只需将此区间的end
(由第三部分id
标识)添加到集合中。如果集合的大小超过限制,我们必须确切地删除一个间隔,但哪个间隔最适合删除?当然,它是具有最大end
的区间,因为删除此区间不仅可以帮助您减少所需的间隔数以适应限制,而且它将在未来最有用,因为它持续最多。只需从集合中删除此间隔(相应的end
将在集合中的最后一个,因为集合按end
的递增顺序排序
我们目前正在处理间隔的end
,在这种情况下,请查看该集。如果它包含指定的end
,则删除它,因为相应的间隔已经结束。如果集合不包含与我们正在处理的end
匹配的end
,那么只需继续迭代到下一个元素,因为这意味着我们已经决定不采用相应的间隔。
如果您需要计算拍摄间隔的数量,甚至打印它们,可以轻松完成。每当你处理一个间隔的end
时,你实际上在集合中找到了这个{{1}},这意味着相应的间隔是一个,你可以将你的答案增加一,打印或者把它放在代表你答案的矢量中。
我的方法的总复杂性是: N Log(N),其中 N 是输入中给出的间隔数。