leetcode刷题(javaScript)——分治思想(二分查找、快速排序)相关场景题总结

分治思想是一种将问题分解成更小的子问题,然后解决子问题并将结果合并的算法设计策略。二分查找、快速排序和折半查找都属于分治思想的经典算法。在leetcode里,分治思想一般结合其他场景出现,构成复合型题目。但是在看题时一定要了解能否用分治思想去解决题目,避免使用复杂度过高的暴力解决方式;尤其是看到强调时间复杂度为O(logn)实现,那很可能是二分法了。

在实现这些分治算法时,通常会遵循以下逻辑:

  1. 分解(Divide):将原始问题分解成更小的子问题。这通常涉及将问题划分成相同规模的子问题,或者将问题划分成规模逐渐减小的子问题。

  2. 解决(Conquer):递归地解决子问题。对每个子问题递归地应用相同的算法,直到子问题规模足够小,可以直接求解。

  3. 合并(Combine):将子问题的解合并成原始问题的解。这一步通常涉及将子问题的解合并起来,得到原始问题的解。

快速排序

快速排序是一种经典的排序算法,采用了分治思想。其思想可以简单概括为以下几步:

  1. 选择一个基准元素(pivot):从待排序数组中选择一个元素作为基准元素。

  2. 分区(Partition):将数组中小于基准元素的元素放在基准元素的左边,大于基准元素的元素放在基准元素的右边,基准元素则位于最终排序位置。

  3. 递归排序:对基准元素左右两侧的子数组分别递归地应用快速排序算法。

  4. 合并:将左侧递归+基准元素+右侧递归合并返回。

快速排序的关键在于分区过程,通过不断地选择基准元素并分区,将数组分成两部分,左边部分小于基准元素,右边部分大于基准元素。递归地对左右两部分进行排序,最终实现整个数组的排序。快速排序的时间复杂度为O(nlogn),在平均情况下具有较高的效率。

function quickSort(arr) {if (arr.length <= 1) return arr;let mid = Math.floor(arr.length / 2);let pivot = arr.splice(mid, 1)[0];let left = [];let right = [];for (let i = 0; i < arr.length; i++) {if (arr[i] < pivot) {left.push(arr[i]);} else {right.push(arr[i]);}}return quickSort(left).concat(pivot).concat(quickSort(right));
}

二分查找

二分查找,也称为折半查找,是一种在有序数组中查找特定元素的算法。它的基本思想是将数组分成两部分,然后确定目标元素可能存在的那一部分,并继续在该部分进行查找,直到找到目标元素或者确定目标元素不存在。

具体的二分查找算法如下:

  1. 首先,确定数组的左边界和右边界,通常初始时左边界为0,右边界为数组长度减1。
  2. 计算中间位置的索引,即(left + right) / 2。
  3. 比较中间位置的元素与目标元素的大小关系:
    • 如果中间位置的元素等于目标元素,则找到了目标元素,返回其索引。
    • 如果中间位置的元素大于目标元素,则目标元素可能在左半部分,更新右边界为中间位置减1。
    • 如果中间位置的元素小于目标元素,则目标元素可能在右半部分,更新左边界为中间位置加1。
  4. 重复步骤2和步骤3,直到找到目标元素或者左边界大于右边界。

二分查找的时间复杂度为O(log n),其中n为数组的长度。由于每次查找都将数组规模减半,因此它的查找效率非常高。

 二分查找并插入元素示例:

function binarySearchInsert(arr, target) {let left = 0;let right = arr.length - 1;while (left <= right) {let mid = Math.floor((left + right) / 2);if (arr[mid] === target) {// 如果找到目标元素,则直接插入在该位置arr.splice(mid, 0, target);return arr;} else if (arr[mid] < target) {left = mid + 1;} else {right = mid - 1;}}// 如果未找到目标元素,则插入在合适位置arr.splice(left, 0, target);return arr;
}// 示例
const sortedArr = [1, 3, 5, 7, 9];
const target = 6;
const result = binarySearchInsert(sortedArr, target);
console.log(result);

704. 二分查找 

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

 最原始的二分查找题目,如果target存在,那么在left和right无限逼近时一定会遍历完所有的元素,肯定会找到mid下标。如果不存在,while循环结束直接返回-1即可。

/*** @param {number[]} nums* @param {number} target* @return {number}*/
var search = function (nums, target) {let left = 0, right = nums.length - 1;let mid;while (left <= right) {mid = Math.floor((left + right) / 2);if (nums[mid] === target) return mid;if (nums[mid] < target) {left = mid + 1;} else {right = mid - 1;}}return -1;
};

复杂度分析

    时间复杂度:O(log⁡n)O(\log n)O(logn),其中 nnn 是数组的长度。

    空间复杂度:O(1)O(1)O(1)。

 

374. 猜数字大小

猜数字游戏的规则如下:

  • 每轮游戏,我都会从 1 到 n 随机选择一个数字。 请你猜选出的是哪个数字。
  • 如果你猜错了,我会告诉你,你猜测的数字比我选出的数字是大了还是小了。

你可以通过调用一个预先定义好的接口 int guess(int num) 来获取猜测结果,返回值一共有 3 种可能的情况(-11 或 0):

  • -1:我选出的数字比你猜的数字小 pick < num
  • 1:我选出的数字比你猜的数字大 pick > num
  • 0:我选出的数字和你猜的数字一样。恭喜!你猜对了!pick == num

返回我选出的数字。

使用二分思想,找mid元素,通过leetcode提供的隐式guess方法获取mid是否找对。在left和right移动中,mid一定会找到该元素,因为一直都没找到,最后mid、left会和right重合,那么最后那个元素肯定是的了。

根据guess提供的-1还是1可以区分下次二分的位置是在左边还是右边

/** * Forward declaration of guess API.* @param {number} num   your guess* @return 	     -1 if num is higher than the picked number*			      1 if num is lower than the picked number*               otherwise return 0* var guess = function(num) {}*//*** @param {number} n* @return {number}*/
var guessNumber = function (n) {if (n == 1) return n;let left = 1, right = n;while (left <= right) {let mid = Math.floor((left + right) / 2);let gue = guess(mid);if (gue === 0) { return mid; }if (gue === -1) {right = mid - 1;} else {left = mid + 1;}}
};

35. 搜索插入位置

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

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

/*** @param {number[]} nums* @param {number} target* @return {number}*/
var searchInsert = function (nums, target) {let left = 0, right = nums.length - 1;let mid;while (left <= right) {mid = Math.floor((left + right) / 2);if (nums[mid] === target) {return mid;}if (nums[mid] < target) {left = mid + 1;} else {right = mid - 1;}}return left;
};

69. x 的平方根 

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

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

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

这道题也是二分法的变种,只不过对中间元素的要求多了一步,即mid*mid要与x进行比较。

整体是对0-x进行折半查找,找到一个元素,使得它的平方接近于x。就要对left和right进行左右逼近目标元素。这里如果mid*mid=x则返回mid。如果没有,那么循环结束后左右指针会指向同一个元素,而这个元素的平方肯定大于x。题目要求向下取整,所以在循环外返回的是left-1

/*** @param {number} x* @return {number}*/
var mySqrt = function (x) {let left = 0; right = x;let mid;while (left <= right) {mid = Math.floor((left + right) / 2);if (mid * mid == x) {return mid;}if (mid * mid > x) {right = mid - 1;} else {left = mid + 1;}}return left-1;
};

367. 有效的完全平方数

给你一个正整数 num 。如果 num 是一个完全平方数,则返回 true ,否则返回 false

完全平方数 是一个可以写成某个整数的平方的整数。换句话说,它可以写成某个整数和自身的乘积。

不能使用任何内置的库函数,如  sqrt

 这道题跟上面是类似的,只不过不返回具体的值,而是true或false

/*** @param {number} num* @return {boolean}*/
var isPerfectSquare = function (num) {let left = 0, right = num;let mid = 0;while (left <= right) {mid = Math.floor((left + right) / 2);if (mid * mid == num) return true;if (mid * mid < num) {left = mid + 1;} else {right = mid - 1;}}return false;
};

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

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

相关文章

C语言分析基础排序算法——计数排序

目录 计数排序 计数排序基本思路 计数排序改进思路 计数排序 计数排序又称为鸽巢原理&#xff0c;是对哈希直接定址法的变形应用。具体思路为&#xff1a; 统计相同元素出现次数根据统计的结果将序列回收到原来的序列中 计数排序基本思路 基本思路分析&#xff1a; //以…

安卓项目:app注册/登录界面设计

目录 第一步&#xff1a;设计视图xml 第二步&#xff1a;编写登录和注册逻辑代码 运行效果展示&#xff1a; 总结&#xff1a; 提前展示项目结构&#xff1a; 第一步&#xff1a;设计视图xml 在layout目录下面创建activity_login.xml和activity_main.xml文件 activity_lo…

19.创建帖子

文章目录 一、建立路由二、开发CreatePostHandler三、编写logic四、编写dao层五、编译测试运行 一、建立路由 这里要稍微注意的是&#xff1a;需要登录后才可以发表帖子&#xff0c;所以需要用到我们之前写的鉴权中间件。中间件对用户携带的token解析成功后&#xff0c;便会将…

String、StringBuilder、StringBuffer 有什么区别?

1、典型回答 String、StringBuilder 和 StringBuffer 都是 Java 语言中&#xff0c;用于操作字符串的类&#xff0c;但它们在性能、可变性和线程安全性方面有一些区别 1、String&#xff1a;不可变字符串类&#xff0c;也就是说一旦创建&#xff0c;它的值就不可变。每次对 S…

Spring boot 集成netty实现websocket通信

一、netty介绍 Netty 是一个基于NIO的客户、服务器端的编程框架&#xff0c;使用Netty 可以确保你快速和简单的开发出一个网络应用&#xff0c;例如实现了某种协议的客户、服务端应用。Netty相当于简化和流线化了网络应用的编程开发过程&#xff0c;例如&#xff1a;基于TCP和U…

数码管的动态显示(二)

1.原理 这个十六进制是右边的dp为高位。 数码管的动态显示&#xff0c;在第一个计数周期显示个位&#xff0c;在第二个周期显示十位&#xff0c;在第三个周期显示百位由于人眼的视觉和数码管的特性&#xff0c;感觉就是显示了234&#xff0c;每个数码管的显示需要从输入的数据里…

Flutter第四弹:Flutter图形渲染性能

目标&#xff1a; 1&#xff09;Flutter图形渲染性能能够媲美原生&#xff1f; 2&#xff09;Flutter性能优于React Native? 一、Flutter图形渲染原理 1.1 Flutter图形渲染原理 Flutter直接调用Skia。 Flutter不使用WebView&#xff0c;也不使用操作系统的原生控件,而是…

labview中6种机械动作的区别

1.单击时转换&#xff1a;单击时转换&#xff0c;需要手动转换或者赋值回复原来状态&#xff1b; 2.释放时转换&#xff1a;释放时时转换&#xff0c;需要手动转换或者赋值回复原来状态&#xff1b; 3.单击时转换保持到鼠标释放&#xff1a;触发两次&#xff0c;自动恢复原来状…

Linux:导出环境变量命令export

相关阅读 Linuxhttps://blog.csdn.net/weixin_45791458/category_12234591.html?spm1001.2014.3001.5482 Linux中的内建命令export命令用于创建一个环境变量&#xff0c;或将一个普通变量导出为环境变量&#xff0c;并且在这个过程中&#xff0c;可以给该环境变量赋值。 下面…

多数问题求解之蒙特卡洛与分治法

多数问题&#xff08;Majority Problem&#xff09;是一个有多种求解方法的经典问题&#xff0c;其问题定义如下&#xff1a; 给定一个大小为 n n n的数组&#xff0c;找出其中出现次数超过 n / 2 n/2 n/2的元素 例如&#xff1a;当输入数组为 [ 5 , 3 , 5 , 2 , 3 , 5 , 5 ] […

【WPS】压缩图片

第一步&#xff1a; 点击插入&#xff0c;点击图片 第二步&#xff1a; 点击图片工具&#xff0c;点击压缩图片 第三步&#xff1a;

Vue3 前端生成随机id( 生成 UUID )

效果展示 封装工具&#xff08;代码展示&#xff09; 重新创建一个文件**/utils/someTools.js**&#xff0c;并在里面写入如下代码。 function Tools() {}Tools.prototype.guid function () {return xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx.replace(/[xy]/g, function (c) {v…

jQuery模态框弹窗提示代码

jQuery模态框弹窗提示代码 下载地址 jQuery模态框弹窗提示代码

Requests教程-17-请求代理设置

上一小节我们学习了requests解决乱码的方法&#xff0c;本小节我们讲解一下requests设置代理的方法。 代理基本原理 代理实际上指的就是代理服务器&#xff0c; 英文叫作proxy server &#xff0c;它的功能是代理网络用户去取得网络信息。形象地说&#xff0c;它是网络信息的中…

【阿里云系列】-基于云效构建部署Springboot项目到ACK

介绍 为了提高项目迭代的速度加速交付产品给客户&#xff0c;我们通常会选择CICD工具来减少人力投入产生的成本&#xff0c;开源的工具比如有成熟的Jenkins&#xff0c;但是本文讲的是阿里云提高的解决方案云效平台&#xff0c;通过配置流水线的形式实现项目的快速部署到服务器…

【数据结构】双向链表及LRU缓存的实现

目录 前言 1. 在原有的自定义链表类 Linked 的基础上&#xff0c;添加新的 “节点添加”方法 addNode(Node node) 测试用例 测试结果 2. 在自定义链表类的基础上&#xff0c;使用双重循环“强力” 判断两个节点是否发生相交 测试用例 测试结果 3. 在自定义链表类的基础上…

基于opencv的手势识别

当然可以&#xff0c;下面是一个使用OpenCV实现简单手势识别&#xff0c;并在摄像头捕捉的视频中描绘出手部轮廓为线条的示例。该代码会读取摄像头流&#xff0c;然后检测出手部&#xff0c;并用线条描绘出手的轮廓。 首先&#xff0c;你需要安装OpenCV库。如果你还没有安装&am…

Vulnhub靶机:Kioptrix_Level1.1

一、介绍 运行环境&#xff1a;Virtualbox 攻击机&#xff1a;kali&#xff08;192.168.56.101&#xff09; 靶机&#xff1a;Kioptrix_Level1.1&#xff08;192.168.56.104&#xff09; 目标&#xff1a;获取靶机root权限和flag 靶机下载地址&#xff1a;https://www.vul…

C语言例2-3:从键盘输入一个正整数(位数小于或等于10),判断其是否是回文数

回文数是将自然数n的各位数字反向排列得到自然数n1&#xff0c;若n1与n相等&#xff0c;则称为回文数&#xff0c;例如12321 //从键盘输入一个正整数&#xff08;位数小于或等于10&#xff09;&#xff0c;判断其是否是回文数 //回文数是将自然数n的各位数字反向排列得到自然数…

(BAT向)Java岗常问高频面试汇总:MyBatis 微服务 Spring 分布式 MySQL等

看面试题可以是为了面试&#xff0c;也可以是对自己学到的东西的一种查漏补缺&#xff0c;更加深刻的去了解一些核心知识点 Spring面试高频问题 问题一&#xff1a;谈 需要zi料 绿色徽【vip1024b】 谈你对spring IOC 和 DI 的理解&#xff0c;它们有什么区别&#xff1f; **问题…