leetcode-11盛最多的水

解法一 双指针

算法

左右边界作为所选的两个边,计算可以盛的水的容量。如果左边的边小,则剔除次边因此左边界向右移,否则右边界左移(即剔除最右侧边),计算当前的水容量。循环至左边界索引大于等于右边界索引。

证明

在当前边集中,以左右边界高度小的边 做边界能盛的水的最大值就是当前计算的值。因为和别的边匹配 最小高度不可能高于自身高度, 并且宽度不可能大于当前的宽度(因为现在所取两个边是目前边的边界)。
因此可以将小的边剔除,因为以他为边的最大值已经计算。

代码

go实现版本

func maxArea(height []int) int {
	var max int
	var i, j = 0, len(height)-1
	for ; i < j; {
		var minHeight int
		var wide =j-i
		if height[i] < height[j] {
			minHeight =height[i]
			i++
		}else {
			minHeight =height[j]
			j--
		}

		if tmp := minHeight * wide; max < tmp {
			max = tmp
		}

	}
	return max
}

解法二:优先队列

算法:

从左到右计算优先队列。不在优先队列的边a和任意边b组合盛的水不可能比在优先队列中边c和d组合多,原因是不在优先队列中说明优先队列中存在 在其左侧的边c的边长大于边a,不然a就会进入优先队列。
然后计算从右到左的优先队列。两个优先队列正交。

代码

// 优先队列解法
// 以最右侧为右边,从最左侧开始向右扫描,分别为a b c ,当扫描完a后扫描b,如果b比左侧的最大值小 那么水量肯定小 则直接跳过。从左到右组成一个优先队列.被剔除的点不可能是最优解
// 同理以最左侧为边,从右向左求优先队列。被踢的点也不可能为最优解

type Queue struct {
	index int
	value int
}

func maxArea1(height []int) int {
	var leftPriority []Queue
	for i := 0; i < len(height); i++ {
		if len(leftPriority) == 0 {
			leftPriority = append(leftPriority, Queue{index: i, value: height[i]})
			continue
		}
		if height[i] > leftPriority[len(leftPriority)-1].value {
			leftPriority = append(leftPriority, Queue{index: i, value: height[i]})
		}
	}
	var rightPriority []Queue
	for i := len(height) - 1; i >= 0; i-- {
		if len(rightPriority) == 0 {
			rightPriority = append(rightPriority, Queue{index: i, value: height[i]})
			continue
		}
		if height[i] > rightPriority[len(rightPriority)-1].value {
			rightPriority = append(rightPriority, Queue{index: i, value: height[i]})
		}
	}

	var max int
	for i := 0; i < len(leftPriority); i++ {
		for j := 0; j<len(rightPriority); j++ {
			if rightPriority[j].index > leftPriority[i].index {
				minHigh := rightPriority[j].value
				if rightPriority[j].value > leftPriority[i].value {
					minHigh = leftPriority[i].value
				}
				if tmpMax := minHigh * (rightPriority[j].index - leftPriority[i].index); tmpMax > max {
					max = tmpMax
				}
				continue
			}
			break
		}
	}
	return max
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值