Java では、後続の崩壊を考慮せずに:
public static int collapse(int[] buildings) {
int i, maxDamage, index, currentDamage;
// do not consider the last building, it will cause only its own fall
maxDamage = 1;
index = buildings.length - 1;
for(i = buildings.length - 1; i >= 0; i--) {
// update maximum damage as the mimimum value between the building[i] (the height of the building at index i) and the remaining number of elements from i to the end of the array
currentDamage = Math.min(buildings[i], buildings.length - i);
System.out.println(currentDamage);
if(currentDamage > maxDamage) {
maxDamage = currentDamage;
index = i;
}
}
return index;
}
私の最終的な解決策は、受け入れられたものとは異なりますが、完全には理解できませんでした。アイデアは、現在のインデックスが崩壊する建物の数を右端の位置から数え始めることです。
index: 7 6 5 4 3 2 1 0
height: 1 3 1 2 4 1 3 2
damage: 1 2 1 2 4 1 3 2
次に、もう一度右端の位置から開始して、累積合計を作成します。右隣のビルから見て最後まで倒壊しなかったビルの数を、現在位置が崩壊するビルの数に加算する。
index: 7 6 5 4 3 2 1 0
height: 1 3 1 2 4 1 3 2
damage: 1 2 1 2 5 1 7 8
結局、ダメージが最大のインデックスを返すだけです。
このソリューションは実行されO(n)
ますが、余分なO(n)
スペースが使用されます。
次のコードは完全なバージョンです (後続の折りたたみでも機能します)。
public static int collapse(int[] buildings) {
int i, maxIndex, max;
int damage[] = new int[buildings.length];
for(i = buildings.length - 1; i >= 0; i--) {
// compute damage for each position
damage[i] = Math.min(buildings[i], buildings.length - i);
}
for(i = buildings.length - 1; i >= 0; i--) {
// update total accumulated damage for each position
if(damage[i] > 1) {
if(damage[i] + i - 1 < buildings.length && i != (i + damage[i] - 1) ) {
damage[i] += damage[i + damage[i] - 1] - 1;
}
}
}
max = damage[0];
maxIndex = 0;
for(i = 1; i < buildings.length; i++) {
// find the maximum damage
if(damage[i] > max) {
max = damage[i];
maxIndex = i;
}
}
return maxIndex;
}