D.二分查找-基础-2529. 正整数和负整数的最大计数

题目链接:2529. 正整数和负整数的最大计数(简单)

算法原理:

解法:二分查找

模板👇

优选算法-二分:18.在排序数组中查找元素的第一个和最后一个位置

利用题目的按 非递减顺序 排列的条件就可以二分处理了,找到负数的最右端点和正数的最左端点

思路一:将二分查找的值设为定值,间接找到不确定的值

击败100.00%

时间复杂度O(Logn)

目标值定为0,因为0恰好是二段性的节点,因此可以有两种角度看待这个目标值0

①左区间最右端的0:-5,-3-2-1,0,0,0,0,1,4,5,6

②右区间最左端的0:-5,-3-2-1,0,0,0,0,1,4,5,6

第一次遍历找到 最左端的0 进而找到 最后一个负数 :

二分查找结束后,left和right在0(没有0就在0的右侧),先处理边界情况,看是否全是负数,是0或者正数就正常更新长度即可

第二次遍历找到 最右端的0 进而找到 第一个正数 :

二分查找结束后,left和right在0(没有0就在0的左侧),先处理边界情况,看是否全是正数,是0或者负数就正常更新长度即可

思路二:直接将二分查找的值设为要找的不确定值

击败100.00%

时间复杂度O(Logn)

比思路一好写一些,但是要理解好每一步,这里的if判断是带等号的,因为0不算正数也不算负数,等于0的时候也要相应移动

答疑

Q1:能不能用一次二分就找到最后的负数和第一个正数呢?

能的,比如先找到最后一个负数的位置,然后left右移找到第一个正数的位置,但是不保证时间复杂度一定是logn,因为当数据-1,0,0,0,0,0,\~,0,0,0,2,的时候left一直右移就会将时间复杂度弱化到O(N),所以两次二分还是更稳妥些

Java代码:

java 复制代码
class Solution {
    public int maximumCount(int[] nums) {
        //利用题目的按 非递减顺序 排列的条件就可以二分处理了
        //找到负数的最右端点和正数的最左端点
        int n=nums.length;
        if(n==0) return 0;
        //利用0来决定二段性:负数 0 正数
        //先找最后一个负数(通过最左侧的0来找)
        int left=0,right=n-1;
        while(left<right){
            int mid=left+(right-left)/2;
            if(nums[mid]<0) left=mid+1;
            else right=mid;
        }
        //此时在0或者0的右侧(正数)
        int neg=0;
        //全是负数
        if(nums[left]<0) neg=n;
        //是0或者正数
        else neg=left;
        //再找第一个正数(通过最右侧的0来找)
        left=0;right=n-1;
        while(left<right){
            int mid=left+(right-left+1)/2;
            if(nums[mid]>0) right=mid-1;
            else left=mid;
        }
        //此时在0或者0的左侧
        int pos=0;
        //全是正数
        if(nums[left]>0) pos=n;
        //是0或者负数
        else pos=n-(left+1);
        return Math.max(neg,pos);
    }
}
java 复制代码
class Solution {
    //思路二:直接将二分查找的值设为要找的不确定值
    public int maximumCount(int[] nums) {
        int n=nums.length;
        if(n==0) return 0;
        int left=0,right=n-1;
        //找到负数的最后一个位置
        while(left<right){
            int mid=left+(right-left+1)/2;
            if(nums[mid]>=0) right=mid-1;
            else left=mid;
        }
        int neg=nums[left]<0?left+1:0;
        //找到正数的第一个位置
        left=0;right=n-1;
        while(left<right){
            int mid=left+(right-left)/2;
            if(nums[mid]<=0) left=mid+1;
            else right=mid;
        }
        int pos=nums[left]>0?n-left:0;
        return Math.max(neg,pos);
    }
}
相关推荐
非优秀程序员6 小时前
第05章 播放器大战,暴风、快播与那一夜|《互联网产品恩仇录》
算法
非优秀程序员6 小时前
第04章 邮箱大战,163 与 QQ 的暗战|《互联网产品恩仇录》
java·vue.js·架构
知已难寻7 小时前
Docker 入门:容器技术与 Docker 基础
java·运维·服务器·docker·云原生·容器
沐晓时光7 小时前
C语言入门,内存函数知识讲解
c语言·开发语言
文丑颜不良啊9 小时前
LeetCode2481~2500题目解析
java·leetcode
Flynn Liang10 小时前
同一需求三套写法:用 Spring AI、LangChain4j、AgentScope Java 各实现一个带工具调用的 RAG 助手(实战对比)
java·人工智能·大模型·架构设计·spring ai·langchain4j·agentscope
聪明的笨猪猪11 小时前
实际工程问题:AI 生成 Spring Cache(@Cacheable / @CachePut / @CacheEvict)缓存注解踩坑
java·经验分享·面试·ai编程
愿有所息11 小时前
记一次 ARM64 + JDK8 上 fastjson2 的诡异数据错乱
java
秋饼11 小时前
MCP 2026-07-28 无状态协议大改版:Spring AI 2.1 多轮往返请求与网关路由落地
java·ai·技术分享·后端开发