Java代码随想录第一章:-数组理论基础,704. 二分查找,27. 移除元素 ,

news2024/11/24 16:44:34

一、数组理论基础

数组是存放在连续内存空间上的相同类型数据的集合。

数组可以方便的通过下标索引的方式获取到下标下对应的数据。

举一个字符数组的例子如图:

需要两点注意的是

  • 数组下标都是从0开始的。
  • 数组内存空间的地址是连续

正是因为数组的在内存空间的地址是连续的,所以我们在删除或者增添元素的时候,就难免要移动其他元素的地址。

例如删除下标为3的元素,需要对下标为3的元素后面的所有元素都要做移动操作,如图所示:

 二、704. 二分查找力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台备战技术面试?力扣提供海量技术面试资源,帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。icon-default.png?t=N7T8https://leetcode.cn/problems/binary-search/

例题:

           给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。

示例 1:

输入: nums = [-1,0,3,5,9,12], target = 9     
输出: 4       
解释: 9 出现在 nums 中并且下标为 4     

示例 2:

输入: nums = [-1,0,3,5,9,12], target = 2     
输出: -1        
解释: 2 不存在 nums 中因此返回 -1   

提示:

  • 你可以假设 nums 中的所有元素是不重复的。
  • n 将在 [1, 10000] 之间。
  • nums 的每个元素都将在 [-9999, 9999] 之间。

算法公开课:手把手带你撕出正确的二分法 | 二分查找法 | 二分搜索法 | LeetCode:704. 二分查找_哔哩哔哩_bilibili

第一种写法:定义在左闭右闭的区间里[left, right] (这个非常重要

区间定义二分法的代码如何写:首先定义target[left, right]区间!

因此有这两点:①while (left <= right) 要使用 <=因为:left == right是有意义的,所以:使用 <=

                         ②if (nums[middle] > targetright 要赋值为 middle - 1因为:当前这个nums[middle]一定不是target,那么接下来要查找的左区间结束下标位置就是 middle - 1

例如:在数组[1,2,3,4,7,9,10]中查找元素2,如图所示:

public class day01 {
    public static void main(String[] args) {
        int nums[] = {1, 3, 7, 9};
        int target = 7;
        System.out.println(search(nums, target));
    }
    //1.左闭右闭的情况
    public static int search(int nums[], int target) {
        //避免当target 小于nums[0] ,nums[nums.lenth-1]时多循环运算
        if (target < nums[0] || target > nums[nums.length - 1]) {
            return -1;// 这里呢进行一个排除 如果说目标的值小于最小,大于最大,那就直接退出
        }
        int left = 0;
        int right = nums.length - 1;// 定义target在左闭右闭的区间里,[left, right]
        while (left <= right) { // 当left==right,区间[left, right]依然有效,所以用 <=
            int middle = left + ((right - left) / 2);// 防止溢出 等同于(left + right)/2
            if (nums[middle] == target)
                return middle;// 数组中找到目标值,直接返回下标
            else if (nums[middle] < target)
                left = middle + 1;// target 在右区间,所以[middle + 1, right]
            else if (nums[middle] > target)
                right = middle - 1; // target 在左区间,所以[left, middle - 1]
        }
        return -1;
    }
}

第二种写法:左闭右开的区间里[left, right) 那么二分法的边界处理方式则截然不同。

有如这两点:

  • while (left < right),这里使用 < ,因为left == right在区间[left, right)是没有意义的
  • if (nums[middle] > target) right 更新为 middle,因为:当前nums[middle]不等于target,去左区间继续寻找,而寻找区间是左闭右开区间,   所以:right更新为middle,即:下一个查询区间不会去比较nums[middle]

在数组:1,2,3,4,7,9,10中查找元素2,如图所示:(注意和方法一的区别

 

    //2.左闭右开的情况
    public static int search2(int nums[], int target) {
        //避免当target 小于nums[0] ,nums[nums.lenth-1]时多循环运算
        if (target < nums[0] || target > nums[nums.length - 1]) {
            return -1;// 这里呢进行一个排除 如果说目标的值小于最小,大于最大,那就直接退出
        }
        int left = 0;
        int right = nums.length - 1;// 定义target在左闭右开的区间里,即:[left, right)
        while (left < right) { // 因为left == right的时候,在[left, right)是无效的空间,所以使用 <
            int middle = left + ((right - left) >> 1);
            if (nums[middle] > target)
                return middle; // target 在左区间,在[left, middle)中
            else if (nums[middle] < target)
                left = middle + 1;// target 在右区间,在[middle + 1, right)中
            else if (nums[middle] == target)
                return middle; // 数组中找到目标值,直接返回下标
        }
        return -1;
    }

三、总结

总体代码:

package com.chapter.one.shuzu;

public class day01 {
    public static void main(String[] args) {
        int nums[] = {1, 3, 7, 9};
        int target = 7;
        System.out.println(search2(nums, target));
    }

    //1.左闭右闭的情况
    public static int search(int nums[], int target) {
        //避免当target 小于nums[0] ,nums[nums.lenth-1]时多循环运算
        if (target < nums[0] || target > nums[nums.length - 1]) {
            return -1;// 这里呢进行一个排除 如果说目标的值小于最小,大于最大,那就直接退出
        }
        int left = 0;
        int right = nums.length - 1;// 定义target在左闭右闭的区间里,[left, right]
        while (left <= right) { // 当left==right,区间[left, right]依然有效,所以用 <=
            int middle = left + ((right - left) / 2);// 防止溢出 等同于(left + right)/2
            if (nums[middle] == target)
                return middle;// 数组中找到目标值,直接返回下标
            else if (nums[middle] < target)
                left = middle + 1;// target 在右区间,所以[middle + 1, right]
            else if (nums[middle] > target)
                right = middle - 1; // target 在左区间,所以[left, middle - 1]
        }
        return -1;
    }

    //2.左闭右开的情况
    public static int search2(int nums[], int target) {
        //避免当target 小于nums[0] ,nums[nums.lenth-1]时多循环运算
        if (target < nums[0] || target > nums[nums.length - 1]) {
            return -1;// 这里呢进行一个排除 如果说目标的值小于最小,大于最大,那就直接退出
        }
        int left = 0;
        int right = nums.length - 1;// 定义target在左闭右开的区间里,即:[left, right)
        while (left < right) { // 因为left == right的时候,在[left, right)是无效的空间,所以使用 <
            int middle = left + ((right - left) >> 1);
            if (nums[middle] > target)
                return middle; // target 在左区间,在[left, middle)中
            else if (nums[middle] < target)
                left = middle + 1;// target 在右区间,在[middle + 1, right)中
            else if (nums[middle] == target)
                return middle; // 数组中找到目标值,直接返回下标
        }
        return -1;
    }
}

Debug测试解析:

①对区间的定义要理解清楚;

②在循环中没有始终坚持根据查找区间的定义来做边界处理;

③区间的定义就是不变量,那么在循环中坚持根据查找区间的定义来做边界处理,就是循环不变量规则;

总结本篇:两种常见的区间定义,给出了两种二分法的写法,每一个边界为什么这么处理,都根据区间的定义做了详细介绍。

------------------希望可以帮助到更多学习Java的小伙伴,不懂或者有疑惑的可以随时来问我哦!

                                                                                                        -------------@程序员~小鱼儿

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1034616.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Unity 发布WebGL平台,C#与JavaScript交互

发布H5平台&#xff0c;接入SDK&#xff0c;比如微信等&#xff0c;涉及到C#与JS的交互。 jslib&#xff08;JavaScript Library&#xff09;是Unity的一种机制&#xff0c;允许你在C#中通过JavaScript代码来执行一些操作。这是一种高级的技巧&#xff0c;主要用于一些特殊情况…

【QT】Qt的随身笔记(持续更新...)

目录 Qt 获取当前电脑桌面的路径Qt 获取当前程序运行路径Qt 创建新的文本文件txt&#xff0c;并写入内容如何向QPlainTextEdit 写入内容QTimerQMessageBox的使用QLatin1StringQLayoutC在c头文件中写#include类的头文件与直接写class加类名有何区别mutable关键字前向声明 QFontQ…

Android AMS——APP启动流程

Android 应用启动方式主要有两种 , 冷启动和热启动。 冷启动:后台没有应用进程 , 需要先创建进程 , 然后启动 Activity ;热启动:后台有应用进程 , 不创建进程 , 直接启动 Activity ; 其实,还有一种问起动的方式,就是用户按了返回键退出应用,随后又从新启动,可是活…

【Python】{已解决}在命令行窗口查看的版本号与安装版本不一致问题

今天在使用一个新的第三方库的时候&#xff1a;先pip安装了一下&#xff0c;然后导入的时候报错了 然后以为是没有安装成功&#xff0c;就又pip了一下&#xff0c;发现已经成功安装了。 那是为什么呢&#xff1f; 是解释器出现了问题吗&#xff1f;于是我就去查看了一下pychar…

反射-认识反射

一、什么是反射 二、如何使用反射 1.第一步&#xff1a;加载类&#xff0c;获取类的字节码&#xff08;获取类的Class对象&#xff09; public class reflectTest {public static void main(String[] args) throws Exception {Class c1 Student.class; //通过类名得到学生类…

上班后很迷茫,到底该如何做一个合格的测试?

【软件测试面试突击班】如何逼自己一周刷完软件测试八股文教程&#xff0c;刷完面试就稳了&#xff0c;你也可以当高薪软件测试工程师&#xff08;自动化测试&#xff09; 如何做一个合格的测试&#xff1f;软件测试工程师的岗位职责到底是什么&#xff1f; 最初&#xff0c;我…

倒计时列表实现(小程序端Vue)

//rich-text主要用来将展示html格式的&#xff0c;可以直接使用这个标签 <view class"ptBox" v-for"(item,index) in orderList" :key"index"> <rich-text :nodes"item.limit_time|limitTimeFilter"></rich-text>…

vue+three.js中使用Ammo.js

直接通过npm i ammo.js安装进webpack的项目里调用时&#xff0c;会出现如下报错&#xff1a; ERROR in ./node_modules/ammo.js/ammo.js 1:1683-1696 Mo…

VMware中安装Ubuntu(2023年)

Ubuntu安装 前言 安装过程中电脑发热时正常的&#xff0c;这个还是稍微有点点大&#xff1b;下载的版本根据自己的喜好来&#xff0c;新版本肯定要比旧版本占用的空间更大&#xff0c;大家自行选择&#xff1b;仅供学习使用的话可以下载成熟稳定的版本&#xff0c;例如16、18…

【新版】系统架构设计师 - 案例分析 - 架构设计<SOA与微服务>

个人总结&#xff0c;仅供参考&#xff0c;欢迎加好友一起讨论 文章目录 架构 - 案例分析 - 架构设计&#xff1c;SOA与微服务&#xff1e;例题1例题2例题3例题4 架构 - 案例分析 - 架构设计&#xff1c;SOA与微服务&#xff1e; 这里SOA与微服务的例题只对应找寻了几个&#x…

servlet开发-通过Tomcat部署一个简单的webapp

首先我们得下载安装Tomcat&#xff0c;推荐看Tomcat&#xff08;HTTP服务器&#xff09;下载以及认识&#xff0c; 我们将通过打印一个hello word的方式来熟悉servlet开发,通过Tomcat部署一个webapp的流程 servlet的含义 Tomcat提供了一系列的api接口&#xff0c;这些api背后…

dfs力扣1993树上的操作

文章目录 dfs力扣1993树上的操作题目示例提示做题历程做题思路数组定义编写代码 完整代码 dfs力扣1993树上的操作 题目 题目链接 给你一棵 n 个节点的树&#xff0c;编号从 0 到 n - 1 &#xff0c;以父节点数组 parent 的形式给出&#xff0c;其中 parent[i] 是第 i 个节点…

Java多线程篇(5)——cas和atomic原子类

文章目录 CASAtomic 原子类一般原子类针对aba问题 —— AtomicStampedReference针对大量自旋问题 —— LongAdder CAS 原理大致如下&#xff1a; 在java的 Unsafe 类里封装了一些 cas 的api。以 compareAndSetInt 为例&#xff0c;来看看其底层实现。 可以发现&#xff0c;最…

基于abaqus的非等速生长Voronoi晶体模型生成插件

1. 非等速生长晶体模型简介 对于标准Voronoi而言&#xff0c;每个晶粒的生长速率是相同的&#xff0c;任意两个晶粒的交界线为其形核点连线的垂直平分线&#xff0c;交界线为一条直线&#xff0c;如图1.1所示。 图1.1 标准Voronoi晶粒交界线 而对于非等速生长Voronoi晶体而言…

项目篇——java文档搜索引擎

Java 文档搜索引擎 文章目录 Java 文档搜索引擎一、分词二、完成parser 类2.1、排除非html文件2.2、解析html以下是解析 HTML 标题的方法以下是解析 对应的 URL以下是解析 HTML的正文&#xff1a; 补充&#xff1a;倒序索引 三、实现 index 类3.1、实现索引结构3.2、索引中新增…

学会使用Git 和 GitHub

Git 和 GitHub 都是程序员每天都要用到的东西 —— 前者是目前最先进的 版本控制工具&#xff0c;拥有最多的用户&#xff0c;且管理着地球上最庞大的代码仓库&#xff1b;而后者是全球最大 同性交友 代码托管平台、开源社区。 在没有这两个工具时&#xff0c;编程可能是这样的…

Go环境搭建

下载 官网地址 选择Download 根据自己的请选择对应的版本进行下载(我这里使用windos go.1.21.1版本) 我这里选择zip类型进行下载免安装版(你也可以选择mis类型进行下载,安装版一步一步next就行)。 安装 解压安装包 目录说明 配置环境变量 验证是否安装成功 完成上述配置…

通过插件去除Kotlin混淆去除 @Metadata标记

在Kotlin中&#xff0c;Metadata是指描述Kotlin类的元数据。它包含了关于类的属性、函数、注解和其他信息的描述。Metadata的作用主要有以下几个方面&#xff1a; 反射&#xff1a;Metadata可以用于在运行时获取类的信息&#xff0c;包括类的名称、属性、函数等。通过反射&…

【功能设计】数据分发功能设计

文章目录 设计脑图功能性非功能性 功能设计文档1. 需求分析1.1、功能性需求1.2、非功能性需求 2. 功能设计2.1 业务流程图2.2 数据流图2.3 表结构设计2.4 接口设计2.5 功能点 3.非功能性设计3.1 性能3.2 可用性3.3 并发性3.4 安全性 设计脑图 功能性 非功能性 功能设计文档 1…

国庆中秋特辑(三)使用生成对抗网络(GAN)生成具有节日氛围的画作,深度学习框架 TensorFlow 和 Keras 来实现

要用人工智能技术来庆祝国庆中秋&#xff0c;我们可以使用生成对抗网络&#xff08;GAN&#xff09;生成具有节日氛围的画作。这里将使用深度学习框架 TensorFlow 和 Keras 来实现。 一、生成对抗网络&#xff08;GAN&#xff09; 生成对抗网络&#xff08;GANs&#xff0c;…