题目为 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
思路将数组的位置以及值存储到键值对中,并排序。找到最高点,分别向左、右计算水量,水量为最低的边乘以距离。减去两边之间的数组值,代码如下
public int Trap(int[] height)
{
if (height==null||height.Count()==0)
{
return 0;
}
int count = height.Count();
Dictionary<int, int> dic = new Dictionary<int, int>();
for (int i = 0; i < count; i++)
{
dic.Add(i,height[i]);
}
Dictionary<int, int> sort= dic.OrderByDescending(e => e.Value).ToDictionary(p => p.Key, o => o.Value);
//左侧体积计算
int res = 0;
int maxTempPlace = sort.First().Key;
int maxTempPlaceRIght = sort.First().Key;
foreach (var item in sort)
{
if (item.Key < maxTempPlace)
{
res += (maxTempPlace - item.Key-1) * height[item.Key];
for (int i = item.Key + 1; i < maxTempPlace; i++)
{
res -= height[i];
}
maxTempPlace = item.Key;
}
else if (item.Key > maxTempPlaceRIght)
{
res += (item.Key - maxTempPlaceRIght - 1) * height[item.Key];
for (int i = maxTempPlaceRIght + 1; i < item.Key; i++)
{
res -= height[i];
}
maxTempPlaceRIght = item.Key;
}
}
return res;
}
第二种是双指针,左右两侧同时向中间移动,如外侧比内测大,则相邻相减为贡献的水的体积。代码如下
public int Trap(int[] height)
{
int left = 0, right = height.Length - 1;
int res = 0;
int leftMax = 0, rightMax = 0;
//比较两个指针,移动小的那个向中间移动
while (left<right)
{
if (height[left]<height[right])
{
if (leftMax < height[left])
{
leftMax= height[left];
}
else
{
//差值为可接水的体积
res += (leftMax-height[left]);
}
left++;
}
else
{
if (rightMax < height[right])
{
rightMax = height[right];
}
else
{
res += (rightMax - height[right]);
}
right--;
}
}
return res;
}