给出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轮问题)
答案 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拯救高度的方法相结合,你就拥有了一个非常快速的算法。