トピックリンク
タイトル説明:
幅1の各列の高さマップを表すn個の非負の整数が与えられた場合、このように配置された列が受け取ることができる雨水量を計算します。
例:
入力:[0,1,0,2,1,0,1,3,2,1,2,1]
出力:6
暴力
暴力的な方法は、考えやすくなります。つまり、現在のカラムがカラムごとに保持できる雨水量を計算します。現在の列の左端の最大高さとcurMaxLeft
右端の最大高さを見つけ、curMaxRight
両端の最大高さの最小値を比較し、現在の列の高さと比較します。最小値が大きい場合現在の高さよりも、違いは明らかに雨水の量です。それ以外の場合は、パック雨水はありません。
コード
class Solution {
public:
int trap(vector<int>& height) {
if(height.size() < 3)
return 0;
int len = height.size();
int start = 0;
while(start < len && height[start] == 0)
start++;
int curMaxLeft = height[start];
int result = 0;
for(int i = start + 1; i < len - 1; i++){
int curMaxRight = getMax(height, i + 1, len - 1);
int curHeight = min(curMaxLeft, curMaxRight);
if(curHeight - height[i] > 0)
result += curHeight - height[i];
curMaxLeft = max(curMaxLeft, height[i]);
}
return result;
}
private:
int getMax(vector<int>& height, int start, int end){
int result = 0;
for(int i = start; i <= end; i++){
result = max(result, height[i]);
}
return result;
}
};
暴力的な最適化
強引な方法では、現在の列の左端と右端の最大高さを常に取得する必要があることがわかりました。メモを使用して、現在の列の左端と右端の最大の高さを記録して、計算の繰り返しを回避できます。
curMaxLeft [i] = max(curMaxLeft [i-1]、height [i-1]);
curMaxRight [i] = max(curMaxRight [i + 1]、height [i + 1]);
コード
class Solution {
public:
int trap(vector<int>& height) {
if(height.size() < 3)
return 0;
int result = 0;
int len = height.size();
vector<int> curMaxLeft(len);
vector<int> curMaxRight(len);
for(int i = 1; i < len - 1; i++)
curMaxLeft[i] = max(curMaxLeft[i - 1], height[i - 1]);
for(int i = len - 2; i >= 0; i--)
curMaxRight[i] = max(curMaxRight[i + 1], height[i + 1]);
for(int i = 1; i < len - 1; i++){
int cur = min(curMaxLeft[i], curMaxRight[i]);
if(cur - height[i] > 0)
result += cur - height[i];
}
return result;
}
};
2ポインター最適化
次に、スペースの複雑さを軽減することを検討してください。最初の2つの暴力的な解決策を観察すると、左端の最大値が左から右にトラバースされるため、ポインターを使用して左端の最大値をリアルタイムで更新できますが、右端では更新できないことがわかります。サイクルの方向が左から右になると、右端の最大値が右から左にトラバースされます。明らかに、暴力の方法では1つのサイクルでタスクを完了することはできません。
現時点では、実際にはメモの最適化であるデュアルポインタを検討します。メモでは、最初に結果を記録してから計算し、ダブルポインタをリアルタイムで更新します。
コード
class Solution {
public:
int trap(vector<int>& height) {
if(height.size() < 3)
return 0;
int result = 0;
int len = height.size();
int left = 0, right = len - 1;
int curMaxLeft = height[0], curMaxRight = height[len - 1];
while(left <= right){
curMaxLeft = max(curMaxLeft, height[left]);
curMaxRight = max(curMaxRight, height[right]);
if(curMaxLeft > curMaxRight){
result += curMaxRight - height[right];
right--;
}
else{
result += curMaxLeft - height[left];
left++;
}
}
return result;
}
};
参照リンク
間違いや厳しくない場合は訂正してください、ありがとうございます。
私のブログ:http://breadhunter.gitee.io