二分算法入门(简单题)

2024-09-06 17:44
文章标签 算法 简单 入门 二分

本文主要是介绍二分算法入门(简单题),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

习题1

704. 二分查找
 

给定一个 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

提示:

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

写法1:

class Solution {public int search(int[] nums,int target) {if(target < nums[0] || target > nums[nums.length - 1]) {return -1;}int left = 0;int right = nums.length - 1;while(left <= right) {int mid = left + (right - left) / 2;if(nums[mid] > target) {right = mid - 1;}else if (nums[mid] < target) {left = mid + 1;}else {return mid;}}return -1;}
}

上述写法为第一种写法,我们定义的target所在的区间是一个左闭右闭的区间,也就是[left,right]

区间的定义决定了二分法该如何写,此写法target在[left,right]区间,有以下特点:

1. while (left <= right) 要使用 <= ,因为left == right 是有意义的,故要使用 <=

2. if (nums[middle] > target) right 要赋值为 middle - 1,因为当前这个nums[middle] 一定不是target,那么接下来要查找的做区间结束下标位置就是 middle - 1,left 赋值 middle + 1 同理。


写法2:

class Solution {public int search(int[] nums , int target) {if(target < nums[0] || target > nums[nums.length - 1]) {return -1;}int left = 0;int right = nums.length;while(left < right) {int mid = left + (right - left) / 2;if(nums[mid] < target) {left = mid + 1;}else if(nums[mid] > target) {right = mid;}else {return mid;}}return -1;}
}

 该写法则是将target定义在一个左闭右开的区间中,也就是[left,right),此时二分法的边界处理就截然不同

1. while(left < right),这里使用 < ,因为left == right 在区间 [left,right) 是没有意义的.

2. if(nums[mid] > target) right 更新为mid,因为当前nums[mid] 不等于target,去做区间继续寻找,而寻找区间是左闭右开区间,所以right 更新为 mid,而左边界是闭区间,则if(nums[mid] < target) 中,left 更新为 mid + 1.


以下题目均由二分法第一种写法实现


习题2

35. 搜索插入位置

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

请必须使用时间复杂度为 O(log n) 的算法。

示例 1:

输入: nums = [1,3,5,6], target = 5
输出: 2

示例 2:

输入: nums = [1,3,5,6], target = 2
输出: 1

示例 3:

输入: nums = [1,3,5,6], target = 7
输出: 4

提示:

  • 1 <= nums.length <= 104
  • -104 <= nums[i] <= 104
  • nums 为 无重复元素 的 升序 排列数组
  • -104 <= target <= 104

 这道题目其实就是在二分算法的壳子上面做了些许点缀,根本上还是二分算法的应用,但是多了一些特殊情况的判断,题解如下:

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

从代码实现上不难看出,这其实就是一个二分算法,只不过在特殊情况下做了一些特殊处理,我这里将特殊情况所产生的结果一一进行了返回(有点笨的方法),在处于"左侧"情况与"右侧"情况中无法查询到的数据位置重新进行了判断.


习题3

69. x 的平方根 

给你一个非负整数 x ,计算并返回 x 的 算术平方根 。

由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。

注意:不允许使用任何内置指数函数和算符,例如 pow(x, 0.5) 或者 x ** 0.5 。

示例 1:

输入:x = 4
输出:2

示例 2:

输入:x = 8
输出:2
解释:8 的算术平方根是 2.82842..., 由于返回类型是整数,小数部分将被舍去。

提示:

  • 0 <= x <= 231 - 1
class Solution {public int mySqrt(int x) {int left = 0;int right = x;while(left <= right) {int mid = left + (right - left) / 2;if((long)mid * mid < x) {left = mid + 1;if(left * left > x) {return mid;}}else if((long)mid * mid > x) {right = mid - 1;if((long)right * right < x) {return right;}}else {return mid;}}return -1;}
}

这道题目相对上面那道题目又多了一些变化.除了如习题2一般要对特殊条件再判断外,还需要考虑if((long)mid * mid < x)   if中条件的变化,我们需要按照题目所给的比较依据来判断if中的条件.

这篇关于二分算法入门(简单题)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1142687

相关文章

Python中Request的安装以及简单的使用方法图文教程

《Python中Request的安装以及简单的使用方法图文教程》python里的request库经常被用于进行网络爬虫,想要学习网络爬虫的同学必须得安装request这个第三方库,:本文主要介绍P... 目录1.Requests 安装cmd 窗口安装为pycharm安装在pycharm设置中为项目安装req

SpringBoot简单整合ElasticSearch实践

《SpringBoot简单整合ElasticSearch实践》Elasticsearch支持结构化和非结构化数据检索,通过索引创建和倒排索引文档,提高搜索效率,它基于Lucene封装,分为索引库、类型... 目录一:ElasticSearch支持对结构化和非结构化的数据进行检索二:ES的核心概念Index:

GO语言实现串口简单通讯

《GO语言实现串口简单通讯》本文分享了使用Go语言进行串口通讯的实践过程,详细介绍了串口配置、数据发送与接收的代码实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要... 目录背景串口通讯代码代码块分解解析完整代码运行结果背景最近再学习 go 语言,在某宝用5块钱买了个

SpringCloud Stream 快速入门实例教程

《SpringCloudStream快速入门实例教程》本文介绍了SpringCloudStream(SCS)组件在分布式系统中的作用,以及如何集成到SpringBoot项目中,通过SCS,可... 目录1.SCS 组件的出现的背景和作用2.SCS 集成srping Boot项目3.Yml 配置4.Sprin

SpringBoot整合Apache Spark实现一个简单的数据分析功能

《SpringBoot整合ApacheSpark实现一个简单的数据分析功能》ApacheSpark是一个开源的大数据处理框架,它提供了丰富的功能和API,用于分布式数据处理、数据分析和机器学习等任务... 目录第一步、添加android依赖第二步、编写配置类第三步、编写控制类启动项目并测试总结ApacheS

C++简单日志系统实现代码示例

《C++简单日志系统实现代码示例》日志系统是成熟软件中的一个重要组成部分,其记录软件的使用和运行行为,方便事后进行故障分析、数据统计等,:本文主要介绍C++简单日志系统实现的相关资料,文中通过代码... 目录前言Util.hppLevel.hppLogMsg.hppFormat.hppSink.hppBuf

SpringMVC配置、映射与参数处理​入门案例详解

《SpringMVC配置、映射与参数处理​入门案例详解》文章介绍了SpringMVC框架的基本概念和使用方法,包括如何配置和编写Controller、设置请求映射规则、使用RestFul风格、获取请求... 目录1.SpringMVC概述2.入门案例①导入相关依赖②配置web.XML③配置SpringMVC

MySQL索引踩坑合集从入门到精通

《MySQL索引踩坑合集从入门到精通》本文详细介绍了MySQL索引的使用,包括索引的类型、创建、使用、优化技巧及最佳实践,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友... 目录mysql索引完整教程:从入门到入土(附实战踩坑指南)一、索引是什么?为什么需要它?1.1 什么

Java Lettuce 客户端入门到生产的实现步骤

《JavaLettuce客户端入门到生产的实现步骤》本文主要介绍了JavaLettuce客户端入门到生产的实现步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要... 目录1 安装依赖MavenGradle2 最小化连接示例3 核心特性速览4 生产环境配置建议5 常见问题

深入理解Mysql OnlineDDL的算法

《深入理解MysqlOnlineDDL的算法》本文主要介绍了讲解MysqlOnlineDDL的算法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小... 目录一、Online DDL 是什么?二、Online DDL 的三种主要算法2.1COPY(复制法)