怎么解决这个问题?

时间:2016-09-24 20:10:57

标签: algorithm data-structures

最近在我的访谈中,我被问到一个算法问题:

给出n行草H [n]的高度。农民进行以下操作k次 - > 选择起始索引(s),结束索引(e)和高度(h)。将他的草修剪工具固定在高度h,并将草从行-s修剪成行-e。意思是,对于s和e之间的每个H [i],H [i] = min(H [i],h)。
k次操作后打印所有高度。

注意 - >如果H [i]为6且h为4,则在修整后H [i]变为4(不会减少4)

禁止使用段/芬威克树,访谈需要比O(nk)更好的东西。怎么解决这个问题?

问题也可以在这里找到 http://www.geeksforgeeks.org/directi-interview-set-12-on-campus/ (第4轮问题)

1 个答案:

答案 0 :(得分:0)

想法是删除冗余操作,然后在执行min(H [i],h)时直接通过数组,保留所有高度,这将是O(n)。删除冗余操作需要您对它们进行排序,因此复杂度为O(n + klog(k)+ k)= O(n + klog(k))。

要删除冗余操作,您首先会根据初始位置对它们进行排序。

然后:

for(int x=0;x<oper.length;x++){
    int curr = x+1;
    while(oper[curr].start<oper[x].end){
        if(oper[curr].height > oper[x].height)
            oper[curr].start = oper[x].end;// When you for through the operations you will go from the start to the end of it, if the start is after the end you will not trim
        else { // oper[curr].height<=oper[x].height
            if(oper[x].end<oper[curr].end){
                oper[x].end = oper[curr].start;
            }
            else {
                /**
                 * Make another operation that starts at the end of oper[curr]
                 * and ends at the end of oper[x], and insert it accordingly
                 * in oper. Then make oper[x] end at oper[curr].start
                 * */
            }
        }
        curr++;
    }
}
// Now no operation overlaps with one another.
// When operations where overlapping only the minimum was saved

// Now trim
for(int x = 0;x<oper.length;x++){
    for(int s = oper[x].start;s<oper[x].end;s++){
        h[s] = min(oper[x].height,h[s]);
    }
}

将此与Dominique拯救高度的方法相结合,你就拥有了一个非常快速的算法。