019_接雨水

知识点:动态规划、双指针、单调栈

LeetCode第四十二题:https://leetcode-cn.com/problems/trapping-rain-water/submissions/

这题可谓经典,被各种解法秀一脸

语言:GoLang

// 单调栈
func trap(height []int) int {
    length := len(height)

    if length < 3 {
        return 0
    }

    sum := 0
    stack := []int{}
    for i := 0; i < length; i++ {
        for len(stack) > 0 && height[i] > height[stack[0]] {
            top := stack[0]
            stack = stack[1:]
            if len(stack) == 0 {
                break
            }

            l := stack[0]
            r := i
            h := min(height[l], height[r]) - height[top]
            if h > 0 {
                sum += (r - l - 1) * h
            }
        }
        stack = append([]int{i}, stack...)
    }

    return sum
}
// 双指针版本
func trap___(height []int) int {
    length := len(height)
    if length < 3 {
        return 0
    }

    sum := 0
    left, right := 0, length - 1
    leftMax, rightMax := height[left], height[right]
    for left < right {
        leftMax = max(leftMax, height[left])
        rightMax = max(rightMax, height[right])

        if leftMax < rightMax {
            sum += leftMax - height[left]
            left++
        }else {
            sum += rightMax - height[right]
            right--
        }
    }

    return sum
}
func max(a int, b int) int {
    if a > b {
        return a
    }
    return b
}



// dp解法:先O(n)遍历两次,分别保存每个元素的左右max值
func trap__(height []int) int {
    length := len(height)

    if length < 3 {
        return 0
    }

    // 先遍历两次,计算每个元素的左右Max
    leftMax, rightMax := make([]int, length), make([]int, length)
    leftMax[0], rightMax[length - 1] = height[0], height[length - 1]
    for j := 1; j < length; j++ {
        leftMax[j] = leftMax[j - 1]
        if leftMax[j] < height[j] {
            leftMax[j] = height[j]
        }
    }
    for j := length - 2; j >= 0; j-- {
        rightMax[j] = rightMax[j + 1]
        if rightMax[j] < height[j] {
            rightMax[j] = height[j]
        }
    }

    // 主体逻辑
    sum := 0
    for i := 1; i < length - 1; i++ {
        area := min(leftMax[i], rightMax[i]) - height[i]
        if area > 0 {
            sum += area
        }
    }

    return sum
}


// 朴素版本解法
func trap_(height []int) int {
    length := len(height)

    if length < 3 {
        return 0
    }

    sum := 0
    for i := 1; i < length - 1; i++ {

        leftMax, rightMax := 0, 0
        for j := 0; j < i; j++ {
            if leftMax < height[j] {
                leftMax = height[j]
            }
        }
        for j := length - 1; j > i; j-- {
            if rightMax < height[j] {
                rightMax = height[j]
            }
        }

        area := min(leftMax, rightMax) - height[i]
        if area > 0 {
            sum += area
        }
    }

    return sum
}

func min(a int, b int) int {
    if a > b {
        return b
    }
    return a
}
posted @ 2020-03-14 15:04  Cenyol  阅读(92)  评论(0)    收藏  举报