前缀和以及二分法解题

2023-11-14

1、寻找数组的中心索引

解法1:初始解法

思路: 长度为1的数组,中心索引一定是它本身的那个唯一元素,左右两边的和都为0。

长度为2的数组,除非两个元素都为0 那么这样才存在中心索引,且选最左边的0

长度大于等于2的数组:我们现在讨论普遍的情况,令索引 i 左边的值相加和索引右边的值相加的和作比较,相等的话直接返回i。太慢了!!!

public static int pivotIndex1(int[] nums) {
    if(nums.length == 1) return 0;
    if(nums.length == 2 && nums[0] == 0 && nums[nums.length-1] == 0){
        return 0;
    }
    if(nums.length >= 2){
        for(int i=0;i < nums.length;i++){
            int sum1 = 0;
            int sum2 = 0;
            for(int t = 0; t < i;t++){
                sum1 += nums[t];
            }
            for(int s = nums.length-1;s > i;s--){
                sum2 += nums[s];
            }
            if(sum1 == sum2){
                return i;
            }
        }
    }
    return -1;
}
//执行用时:519 ms, 在所有 Java 提交中击败了5.04%的用户
//内存消耗:38.8 MB, 在所有 Java 提交中击败了82.22%的用户

解法2:

思路:利用前缀和进行解题

什么是前缀和?前缀和是一个数组的某项下标之前(包括此项元素)的所有数组元素的和。

在这里插入图片描述
分析本题:这是一道前缀和的裸题

只需要用两个数组,前后处理两遍前缀和,再对两个前缀和数组的相同下标进行判别即可。

为了简化数组越界判断,我们通常会给前缀和数组多预留一位作为哨兵。这里由于要求数组前后 算上的前缀和。所以我们直接给数组多开两位即length = n+2

public int pivotIndex2(int[] nums) {
    int n = nums.length;
    int[] s1 = new int[n + 2], s2 = new int[n + 2];
    //正着的前缀和数组,注意这里的i 是从1 与 n 开始的
    for (int i = 1; i <= n; i++) s1[i] = s1[i - 1] + nums[i - 1];
    //反着的前缀和数组
    for (int i = n; i >= 1; i--) s2[i] = s2[i + 1] + nums[i - 1];
    for (int i = 1; i <= n; i++) {
        if (s1[i] == s2[i]) return i - 1;
    }
    return -1;
}
//执行用时: 2 ms
//内存消耗: 38.8 MB

解法3:

思路:转换思路解题,中心下标左右的元素相加之和相等,转换成——左边求和*2 + 中心索引值 = 总和;

public int pivotIndex(int[] nums) {
    //求总和
    int sum = 0;
    for(int i = 0;i<nums.length;i++){
        sum += nums[i];
    }
    //求索引左边的和
    int cur = 0;
    for(int i = 0;i < nums.length;++i){
        cur +=nums[i];
        //cur先加了,然后就是需要减一个多的中心索引值
        if(2*cur-nums[i] == sum) return i;
    }
    return -1;
}
//执行用时: 1 ms
//内存消耗: 39.2 MB

2、搜索插入位置

解法一:(初识解法)

给定一个 排序数组 和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中, 返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。

public int searchInsert(int[] nums, int target) {
    int num = 0;
    //目标值存在
    for(int i = 0;i < nums.length;i++){
        if(nums[i] == target){
            num = i;
        }
    }
    //目标值不存在,寻找应该插入的位置
    if(num == 0){
        for(int i = 0;i<nums.length;i++){
            if(i == 0){
                if(target < nums[i]){
                    num = 0;
                }
            }
            if(i >=0 && i< nums.length-1){
                if(target > nums[i] && target < nums[i+1]){
                    num = i+1;
                }
            }else{
                if(target > nums[i]){
                    num = i+1;
                } 
            }
        }
    }
    return num;
}
//执行用时: 1 ms
//内存消耗: 37.9 MB

解法二:暴力解法

public int searchInsert(int[] nums, int target) {
    for(int i = 0; i < nums.length;i++){
        if(nums[i] >= target){
            return i;
        }
    }
return nums.length;
//执行用时: 0 ms
//内存消耗: 38 MB

解法三:二分法(题目给的是有序数组无重复元素

二分法详解

 public int searchInsert(int[] nums, int target) {
     int left = 0;
     int right = nums.length-1;
     while(left <= right){
         int mid = left + ((right-left)/2); //防止溢出
         if(nums[mid] == target){
             return mid;
         }else if(nums[mid] > target){
             right = mid - 1;
         } else if(nums[mid] < target){
             left = mid + 1;
         }
     }
     return right +1;
 }

总结:二分法查找的常用格式

int binarySearch(int[] nums, int target) {
    int left = 0, right = ...;

    while(...) {
        int mid = mid = left + (right - left) / 2;
        //等同于mid = (right + left) / 2,但是上面的写法可以防止溢出!!!
        //先记住防溢出写法!
        if (nums[mid] == target) {
            ...
        } else if (nums[mid] < target) {
            left = ...
        } else if (nums[mid] > target) {
            right = ...
        }
    }
    return ...;
}

注意: . . . 标记的部分是需要注意的细节问题

分析二分查找的一个技巧是:不要出现 else,而是把所有情况用 else if 写清楚,这样可以清楚地展现所有细节

二分查找算法的一个简单举例:寻找一个有序数组中的元素,有返回该数索引,没有就返回-1;

int binarySearch(int[] nums, int target) {
   int left = 0;
   int right = nums.length -1;
   while(left <= right){
       int mid = left + ((right-left)/2); //防止溢出
       if(nums[mid] == target){
           return mid;
       }else if(nums[mid] < target){
           left = mid +1;
       }else if(nums[mid] > target){
           rigth = mid -1;
       }
   }
    return -1;
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

前缀和以及二分法解题 的相关文章

随机推荐

  • 并发下sftp连接报错——com.jcraft.jsch.JSchException: connection is closed by foreign host

    当对单接口极限测试时 随着并发量上升 接口稳定性出现不稳定的情况 排查后台日志 发现报错在该接口调用sftp上传时出现问题 确切的是在初始化连接时失败 原因 系统SSH终端连接数配置过小 查看虚拟机该参数 该参数在 etc ssh sshd
  • 【操作系统】虚拟存储器概述

    存储管理分类 实存管理 分区 Partitioning 连续分配方式 包括固定分区 可变分区 分页 Paging 分段 Segmentation 段页式 Segmentation with paging 虚存管理 请求分页 Demand p
  • java 虚拟机类装载的原理、实现、以及应用

    一 引言 Java虚拟机 JVM 的类装载就是指 将包含在类文件中的字节码装载到JVM中 并使其成为JVM一部分的过程 JVM的类动态装载技术能够在运行时刻动态地加载或者替换系统的某些功能模块 而不影响系统其他功能模块的正常运行 本文将分析
  • python linux运行环境,Linux平台Python运行环境配置

    1 软件包管理工具 pip xiaokang localhost sudo yum install python2 pip 查看pip版本 xiaokang localhost pip V 大v pip 8 1 2 from usr lib
  • mysql8和5.7区别_MySQL8.0和MySQL 5的区别

    虽然MySQL8 0 x都出来了 自己一直使用 5 7的版本 对于新的版本今天抽了些时间来了解一下新的特性 而对于新的版本的了解往往都是从版本区别开始的 今天便算是作一个笔记吧 Oracle发布新版本的MySQL时 直接从5 7 x 跳到了
  • Redhat8.2 linux 忘记root密码破解方法 最详细!!!!!

    root密码破解方法 第一步 重启虚拟机 在开机标题界面 选择系统 按E进入 第二步 进入后在含LINUX开头结尾处加上 rd break 然后按CTRL X进入系统 第三步重新挂载根目录并给予读写权限 否则无法重置密码 第四步切换根目录位
  • TCP通信详解

    一 TCP简介 1 TCP介绍 a gt TCP协议 TCP协议 传输控制协议 英语 Transmission Control Protocol 缩写为 TCP 是一种面向连接的 可靠的 基于字节流的通信协议 1 面向连接 先连接 再通信
  • 疯壳-鸿蒙OS-HDF驱动框架

    一 简介 HDF HarmonyOS Driver Foundation 驱动框架 为驱动开发者提供驱动框架能力 包括驱动加载 驱动服务管理和驱动消息机制 旨在构建统一的驱动架构平台 为驱动开发者提供更精准 更高效的开发环境 力求做到一次开
  • 网络安全毕业设计题目大全

    文章目录 0 简介 1 如何选题 2 最新网安毕设选题 0 简介 毕业季马上就要开始了 不少同学询问学长管理选题开题类的问题 今天跟大家分享信息安全毕设选题 最新的信息安全 网络安全 专业毕设选题 难度适中 适合作为毕业设计 大家参考 学长
  • RuntimeError:shape ‘[4, 3, 85, 80, 80]‘ is invalid for input of size 537600

    在对yolov5进行剪枝训练时出现以下类型的错误 错误原因 1 使用自己 的数据集时 数据集与源代码的数据集的类别数不同 没有修改成对应的类别数 解决办法 修改cfg文件 把classes和filters进行修改 filters class
  • 启用电脑对远程服务器的访问,未启用对服务器的远程访问 win10家庭版

    未启用对服务器的远程访问 win10家庭版 卡饭网 本站整理 2019 07 09 这个问题比较常见小编整理的解决方法如下 方法一 用QQ远程协助对方电脑 需要QQ告诉对方右键单击计算机 这台电脑 点管理 打开计算机管理界面 选择本地用户和
  • git 工具使用--分支管理

    git 工具使用 分支管理 文章目录 git 工具使用 分支管理 理解分支 创建分支 切换分支 合并分支 删除分支 合并冲突 分支管理策略 分支策略 bug分支 删除临时分支 总结 理解分支 分支管理是Git的杀手级功能之一 分支 就是科幻
  • Ajax的核心技术XMLHttpRequest方法

    整个Ajax技术紧紧围绕在XMLHttpRequest对象的周围 Ajax整个技术的过程如下 XMLHttpRequest发送请求 在与服务器交互中 其readyState状态可以监听到服务器 的响应状态 当服务器的响应完成的时候 XMLH
  • 【UiBot】RPA流程机器人有几种类型?

    RPA Robotic Process Automation 机器人流程自动化 是指通过软件自动化方式 使各个行业中本来是人工操作计算机完成的业务 实现工作流程的自动化 RPA机器人的交互方式大致可分为两大主要类型 人机交互型和无人值守型
  • JS逆向获取网易云音乐评论并保存到mongodb数据库

    JS逆向获取网易云音乐评论 前言 这段时间 一直在研究JS逆向 今天小试牛刀一下 利用JS逆向技术获取网易云音乐评论 一 分析网页 其实网易云音乐评论的api很好找到的 我们通过F12进入到浏览器 chrome 的开发者模式 因为音乐的评论
  • 递推均值滤波算法---链式队列实现

    目录 为什么要写这篇 为什么要用队列实现 程序是怎么实现的 程序实现结果 程序代码 为什么要写这篇 仍记得当初写了一篇去除极值的均值滤波算法相关的博客 该算法用在了ADC采样上面 当初偶然看见还有一种递推均值滤波算法 用在了实时波形输出上面
  • F2FS – A New Flash File System for Mobile Devices – ELCE 2012

    本文转载至 http www cnx software com 2013 01 15 f2fs a new flash file system for mobile devices elce 2012 Joo Young Hwang pri
  • 计算机视觉方面的代码

    Jia Bin Huang同学收集了很多计算机视觉方面的代码 链接如下 https netfiles uiuc edu jbhuang1 www resources vision index html 这些代码很实用 可以让我们站在巨人的肩
  • 罗马数字转换器

    我的CSDN主页 My Python 学习个人备忘录 我的博文推荐 罗马数字转换器 整数转罗马数字 本转换器 以1 3999的正整数为限 看到CSDN 每日一练 python 题目 罗马数字转整数 的练习题目 就想写个 整数转罗马数字 的练
  • 前缀和以及二分法解题

    1 寻找数组的中心索引 解法1 初始解法 思路 长度为1的数组 中心索引一定是它本身的那个唯一元素 左右两边的和都为0 长度为2的数组 除非两个元素都为0 那么这样才存在中心索引 且选最左边的0 长度大于等于2的数组 我们现在讨论普遍的情况