大概思路,先找出所有可能极小值(每次用当前值和上一值进行比较)。最后沿着每个极小值开始进行处理逆向处理,理想时间复杂度介于n和n的平方之间。不说了,上代码,此方法是个人思考,完全没有借鉴任何别人的想法,如有雷同,只是思路相同而已。
public int trap(int[] height) throws Exception {
int containValue = 0;
if (height.length == 0) {
throw new Exception("数组长度不能为0");
}
int[] derivativeArr = new int[height.length];
//记录为递减函数的数组下标值
List<Integer> negativeList = new ArrayList<Integer>();
int preValue = 0;
for (int i = 0; i < height.length; i++) {
if (height[i] > preValue) {//递增关系
derivativeArr[i] = 1;
} else if (height[i] == preValue) {//不变
derivativeArr[i] = 0;
} else {
derivativeArr[i] = -1;
negativeList.add(i);
}
preValue = height[i];
}
int[] negativeArr = new int[5];
negativeArr[2] = 1;
negativeArr[3] = 0;
while (negativeArr[2] == 1) {
negativeArr = getNegativeArr(negativeList, negativeArr[3], derivativeArr);
int rightBoundaryValue = 0;
int leftBoundaryValue = height[negativeArr[0] - 1];
int rightBoundary = 0;
int leftBoundary = negativeArr[0] - 1;
if (negativeArr[2] == 0 && negativeArr[4] == 1) {
//当表示为最后一个盛水容器时,判断此次容器是否能装水,当negativeArr[1]不等于0时,可能继续装水,需要derivativeArr数组在边界值以后>0的情况
if (negativeArr[1] != 0) {
int lastNegative = negativeArr[1];
while (lastNegative < derivativeArr.length - 1) {
//找到最后一个最低谷后面的右边界值
if (derivativeArr[++lastNegative] > 0) {
if (height[lastNegative] > rightBoundaryValue) {
rightBoundaryValue = height[lastNegative];
rightBoundary = lastNegative;
}
}
}
}
} else {
//表示还有其他值
rightBoundaryValue = height[negativeArr[1] - 1];
rightBoundary = negativeArr[1] - 1;
}
//计算其值
if (leftBoundaryValue >= rightBoundaryValue) {
containValue += rightBoundaryValue * (rightBoundary - leftBoundary);
for (int index = leftBoundary+1; index <= rightBoundary; index++) {
containValue -= height[index];
}
} else {
containValue += leftBoundaryValue * (rightBoundary - leftBoundary);
for (int index = leftBoundary; index < rightBoundary; index++) {
containValue -= height[index];
}
}
}
System.out.println("容器总值为:" + containValue);
return containValue;
}
/**
* @return
* @desc 返回的数组中,数组0为左边界,
* 数组1为右边界(为0时则表示没有找到右边界),
* 数组2表示是否有下一个盛水容器的左边界,0即为结束
* @author sam.ye
* @date 2020-1-3 15:33
*/
private int[] getNegativeArr(List<Integer> negativeList, int currentValue, int[] derivativeArr) {
int[] intArr = new int[5];
//获得的左边界
int leftBoundary = negativeList.get(currentValue);
//获得右边界
int rightBoundary = 0;
//初始化为未找到该边界值
Boolean findFlag = false;
int nextNegativeValue = currentValue;
while (nextNegativeValue < negativeList.size() && !findFlag) {
int rightBoundaryTemp = negativeList.get(++nextNegativeValue);
//非连续递减,寻找下一个-1的点
if (leftBoundary != rightBoundaryTemp - 1) {
for (int leftTemp = leftBoundary; leftTemp < rightBoundaryTemp; leftTemp++) {
//找到右边界
if (derivativeArr[leftTemp] > 0) {
rightBoundary = rightBoundaryTemp;
findFlag = true;
break;
}
}
//解决边界问题,如:-1,-1,-1,0,0,1和-1,-1,-1,0,0 俩种问题情况
if (!findFlag) {
rightBoundary = rightBoundaryTemp;
intArr[4]=1;
}
}
}
intArr[0] = leftBoundary;
intArr[1] = rightBoundary;
intArr[3] = nextNegativeValue;
//已经到最后一个负数组
if (nextNegativeValue == negativeList.size() - 1) {
intArr[2] = 0;
} else {
intArr[2] = 1;
}
return intArr;
}