【问题标题】:Maximum sum of the range non-overlapping intervals in a list of Intervals区间列表中范围不重叠区间的最大总和
【发布时间】:2013-08-18 04:47:05
【问题描述】:

有人问我这个问题:
你会得到一个间隔列表。你必须设计一个算法来找到不重叠区间的序列,使区间范围的总和最大。

例如:
如果给定的间隔是:

["06:00","08:30"],
["09:00","11:00"],
["08:00","09:00"],
["09:00","11:30"],
["10:30","14:00"],
["12:00","14:00"]

三个间隔时范围最大化

[“06:00”, “08:30”],
[“09:00”, “11:30”],
[“12:00”, “14:00”],

被选中。

因此,答案是 420(分钟)。

【问题讨论】:

  • 你确定这是动态规划吗?
  • 这是经典的加权活动选择问题。
  • 您的答案不应该是 420 分钟吗?如果这三个是选定的间隔

标签: algorithm dynamic-programming intervals greedy


【解决方案1】:

这是一个标准的间隔调度问题。
可以通过动态规划来解决。

算法
让有n 间隔。 sum[i] 在已排序的区间数组中存储到区间 i 的区间的最大总和。算法如下

Sort the intervals in order of their end timings.
sum[0] = 0
For interval i from 1 to n in sorted array
    j = interval in 1 to i-1 whose endtime is less than beginning time of interval i.
    If j exist, then sum[i] = max(sum[j]+duration[i],sum[i-1])
    else sum[i] = max(duration[i],sum[i-1])

迭代进行n 步骤,在每个步骤中,j 可以使用二分搜索找到,即在log n 时间。 因此算法需要O(n log n) 时间。

【讨论】:

  • 是的,我已经实现了很多,我认为它并不难理解。
【解决方案2】:
public int longestNonOverLappingTI(TimeInterval[] tis){
        Arrays.sort(tis);
        int[] mt = new int[tis.length];
        mt[0] = tis[0].getTime();
        for(int j=1;j<tis.length;j++){
            for(int i=0;i<j;i++){
                int x = tis[j].overlaps(tis[i])?tis[j].getTime():mt[i] + tis[j].getTime();
                mt[j]  = Math.max(x,mt[j]);
            }
        }

        return getMax(mt);
    }


public class TimeInterval implements Comparable <TimeInterval> {
    public int start;
    public int end;
    public TimeInterval(int start,int end){
        this.start = start;
        this.end = end;

    }



    public boolean overlaps(TimeInterval that){
          return !(that.end < this.start || this.end < that.start);
    }

    public int getTime(){
        return end - start;
    }
    @Override
    public int compareTo(TimeInterval timeInterval) {
        if(this.end < timeInterval.end)
            return -1;
        else if( this.end > timeInterval.end)
            return 1;
        else{
            //end timeIntervals are same
            if(this.start < timeInterval.start)
                return -1;
            else if(this.start > timeInterval.start)
                return 1;
            else
                return 0;
        }

    }


}

这是工作代码。基本上这在 O(n^2) 中运行,因为有两个 for 循环。但正如 Shashwat 所说,有办法让它在 O(n lg n) 中运行

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-06-07
    • 2021-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-10
    相关资源
    最近更新 更多