2529. 正整数和负整数的最大计数

239 阅读1分钟

题目:
给你一个按 非递减顺序 排列的数组 nums ,返回正整数数目和负整数数目中的最大值。

  • 换句话讲,如果 nums 中正整数的数目是 pos ,而负整数的数目是 neg ,返回 pos 和 neg二者中的最大值。

注意: 0 既不是正整数也不是负整数。

算法:

方法一:二分查找
时间复杂度O(2logn)

func maximumCount(nums []int) int {
    posCount, negCount := 0, 0
    // 找到第一个大于等于0的位置index
    neg := findNegtive(nums)
    pos := findPostive(nums)
    if 0 <= neg && neg < len(nums) {
        negCount = neg + 1
    }
    if 0 <= pos && pos < len(nums) {
        posCount = len(nums) - pos
    }
    return max(posCount, negCount)
}

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

// 找到最大的负数index
func findNegtive(nums []int) int {
    left, right := 0, len(nums) - 1
    for left <= right {
        mid := (left + right) / 2
        if nums[mid] < 0 {
            left = mid + 1
        } else {
            right = mid - 1
        }
    }
    return right
}

// 找到最小的正数index
func findPostive(nums []int) int {
    left, right := 0, len(nums) - 1
    for left <= right {
        mid := (left + right) / 2
        if nums[mid] <= 0 {
            left = mid + 1
        } else {
            right = mid - 1
        }
    }
    return left
}

关于二分多说几句:
1.为什么循环条件是left <= right
考虑nums中只有一个元素,此时left == right,nums[left],nums[right]是正数,负数都有可能,需要和0进行比较,判断left,和right哪个移动。并且每次循环只比较了mid,left + 1 == right时,left,right可能还没有和0比较过。

2.是nums[mid] <= 0 {left = mid + 1 }还是nums[mid] < 0 left = mid + 1, 看你把需不需要0,把0当成正数还是负数处理,为了找最小的正数,把0当成负数处理,就是nums[mid] <= 0 {left = mid + 1 }

3.返回left,还是right
left == right == mid时,可能nums[left]是正数负数都有可能,但肯定是在边界除了。
以findPostive为例,(-无穷,left - 1) <= 0, mid(left,right),0 < (right + 1,+无穷)
如果mid <= 0 则变成了(-无穷,left - 1) <= 0, mid(right),0 < (right + 1(left),+无穷),此时left是最小正数。
如果0 < mid,则变成了(-无穷,left - 1(right)) <= 0, mid(left),0 < (right + 1,+无穷),此时left是最小正数。

方法二:遍历
害,这种朴素方法居然都没有想到了,时间复杂度也就O(n),nums长度也就2000而已。

func maximumCount(nums []int) int {
    posCount, negCount := 0, 0
    // 找到第一个大于等于0的位置index
    for i := range nums {
        if nums[i] > 0 {
           posCount ++ 
        } else if  nums[i] < 0 {
            negCount ++
        }
    }
    return max(posCount, negCount)
}

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