JS Leetcode 81. 搜索旋转排序数组 II 题解,补救二分法的可行性
壹 ❀ 引
今日LeetCode题为153. 寻找旋转排序数组中的最小值,在10个月前,我已在JS leetcode 寻找旋转排序数组中的最小值 题解分析,你不得不了解的二分法一文中写了本题的题解,所以今日的题就不用再写博客记录了。而昨天的题81. 搜索旋转排序数组 II因为思路问题,我先记录了它的普通版33. 搜索旋转排序数组,所以按照约定,今天得把这道题的题解补回来,题目描述如下:
已知存在一个按非降序排列的整数数组 nums ,数组中的值不必互不相同。
在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转 ,使数组变为 [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,4,4,5,6,6,7] 在下标 5 处经旋转后可能变为 [4,5,6,6,7,0,1,2,4,4] 。
给你 旋转后 的数组 nums 和一个整数 target ,请你编写一个函数来判断给定的目标值是否存在于数组中。如果 nums 中存在这个目标值 target ,则返回 true ,否则返回 false 。
示例 1:
输入:nums = [2,5,6,0,0,1,2], target = 0
输出:true
示例 2:
输入:nums = [2,5,6,0,0,1,2], target = 3
输出:false
提示:
1 <= nums.length <= 5000
-104 <= nums[i] <= 104
题目数据保证 nums 在预先未知的某个下标上进行了旋转
-104 <= target <= 104进阶:
这是 搜索旋转排序数组 的延伸题目,本题中的 nums 可能包含重复元素。
这会影响到程序的时间复杂度吗?会有怎样的影响,为什么?
我们先来搜集题目信息,再开始实现它。(这篇文章本来应该昨天发,中午写了一半,晚上加班发版到凌晨1点半,苦不堪言....)
贰 ❀ 题解分析与二分法
我还是推荐,在做本题前,先阅读33. 搜索旋转排序数组一文,因为本题的解题思路将与昨天那篇文章高度相同,仔细阅读题目,会发现唯一不同的地方在于数字不必互不相同,即数组存在重复项,我们以[0,1,1,1,1]寻找0为例,它的旋转情况如下图:

还记得我们上一题的二分规则吗,根据mid与nums[0]的大小对比,判断有序部分在mid的左侧还是右侧,找到了有序部分,就能利用target>=start&&target<mid(有序在左侧)或者target>mid&&target<=end(有序在右侧)来决定放弃掉另一半元素。
但根据上图的第二行,假设旋转为[1,0,1,1,1],虽然mid>=nums[0](为什么是>=上篇文章也有解释),但mid左侧部分居然不是一个有序序列,这就会导致我们的思路不可行,因为重复数字的出现,打破了我们原有二分法的规则,如果挽救这种二分特性呢?其实要做的很简单,如果此次查询出现了左右相等的情况,我们将任意一侧的指针,比如r--,然后不进行后续逻辑跳出循环,相当于重置程序,直到两侧不会出现相同数字,或者重置过程中因为也会重新计算mid遇到target,比如下面这个例子:

当然这个例子显得有些巧,但即便是没遇到,我们也会将数组转变成[1,0]后再进行前面根据mid与nums[0]以及target的比较。
你也许会想,去除掉相同数字不会影响最终结果吗?但我们只是想在数组中找到目标元素,相同的元素本来存在一个就够了,如果数组不存在相同元素,那这题不就是昨天做的那道题了...而本题只是增加了重复元素故意作为了新的考点。
可能看到这,大家还是无法理解为什么为什么这种操作就挽救了前面提到的二分特性,其实问题的根本,只是因为重复元素的存在,导致可能出现左右两侧都是相同元素的情况,比如前面的[1,0,1,1,1],就让我们前面二分法公式无法套用。
大家可以多列几个例子自行验证,所以这道题的解法,仅仅是在昨天那道题的代码基础上,做了一个当左右指针元素相等时修改指针的操作而已,代码如下:
/**
* @param {number[]} nums
* @param {number} target
* @return {boolean}
*/
var search = function (nums, target) {
let l = 0;
let r = nums.length - 1;
while (l <= r) {
const mid = Math.floor((l + r) / 2);
// 如果mid就是目标值直接返回
if (nums[mid] === target) {
return true;
};
// 开始处理左右相同数字的情况
if (nums[l] === nums[r]) {
r--;
// 继续判断还有没有相等的情况,直接跳过后续逻辑
continue;
};
// 下面的逻辑与上一道题一模一样
if (nums[mid] >= nums[l]) {
//target 在 [l, mid] 之间
if (target >= nums[l] && target < nums[mid]) {
r = mid - 1;
} else {
//target 不在 [l, mid] 之间
l = mid + 1;
};
} else {
// [mid, r]有序
// target 在 [mid, r] 之间
if (target > nums[mid] && target <= nums[r]) {
l = mid + 1;
} else {
// target 不在 [mid, r] 之间
r = mid - 1;
}
}
}
return false;
};
所以这道题,只是增加了下面这一小段代码(你让l++也行):
if (nums[l] === nums[r]) {
r--;// 或者l++都行,目的就是为了修复二分行,不让上面那种极端情况出现
continue;
};
而这一小段代码,就像是在不满足二分法情况下,再给程序一次机会一样,不会再修复二分特性,让程序能继续按照我们上道题的思路进行二分,从而判断出最终结果。
JS Leetcode 81. 搜索旋转排序数组 II 题解,补救二分法的可行性的更多相关文章
- Java实现 LeetCode 81 搜索旋转排序数组 II(二)
81. 搜索旋转排序数组 II 假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0,0,1,2,2,5,6] 可能变为 [2,5,6,0,0,1,2] ). 编写一个函数来判 ...
- LeetCode 81——搜索旋转排序数组 II
1. 题目 2. 解答 2.1. 方法一 基于 LeetCode 33--搜索旋转排序数组 中的方法二. 当 nums[mid] = nums[right] 时,比如 [1, 1, 2, 1, 1], ...
- LeetCode 81 - 搜索旋转排序数组 II - [二分+暴力]
假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0,0,1,2,2,5,6] 可能变为 [2,5,6,0,0,1,2] ). 编写一个函数来判断给定的目标值是否存在于数组中. ...
- LeetCode 81 搜索旋转排序数组II
题目: 假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0,0,1,2,2,5,6] 可能变为 [2,5,6,0,0,1,2] ). 编写一个函数来判断给定的目标值是否存在于 ...
- LeetCode 81. 搜索旋转排序数组 II(Search in Rotated Sorted Array II)
题目描述 假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0,0,1,2,2,5,6] 可能变为 [2,5,6,0,0,1,2] ). 编写一个函数来判断给定的目标值是否存在 ...
- Leetcode 81. 搜索旋转排序数组 II
题目链接 https://leetcode-cn.com/problems/search-in-rotated-sorted-array-ii/description/ 题目描述 假设按照升序排序的数 ...
- [LeetCode每日一题]81. 搜索旋转排序数组 II
[LeetCode每日一题]81. 搜索旋转排序数组 II 问题 已知存在一个按非降序排列的整数数组 nums ,数组中的值不必互不相同. 在传递给函数之前,nums 在预先未知的某个下标 k(0 & ...
- 【LeetCode】81. 搜索旋转排序数组 II
81. 搜索旋转排序数组 II 知识点:数组,二分查找: 题目描述 已知存在一个按非降序排列的整数数组 nums ,数组中的值不必互不相同. 在传递给函数之前,nums 在预先未知的某个下标 k(0 ...
- leetcode 33. 搜索旋转排序数组 及 81. 搜索旋转排序数组 II
33. 搜索旋转排序数组 问题描述 假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] ). 搜索一个给定 ...
- 81. 搜索旋转排序数组 II
题目 已知存在一个按非降序排列的整数数组 nums ,数组中的值不必互不相同. 在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋 ...
随机推荐
- 8. exporter
一.已经实现的收集器 1.1 可收集的内存指标 1.2 可收集的jetty指标 二.自定义收集 2.1 summer 2.2 histogram 三.架构设计 exporter作为Prometheus ...
- DEV-C++调试报错
1.报错信息如下: 2.原因 SIGSEGV是是当一个进程执行了一个无效的内存引用,或发生段错误时发送给它的信号. 意思是程序接受一个无效的指针地址,Segmentation fault即是提示我们去 ...
- Linux-网络-子网-子网掩码-网关-DNS解析
- Java中有哪些方式能实现锁某个变量
有的时候博客内容会有变动,首发博客是最新的,其他博客地址可能会未同步,认准https://blog.zysicyj.top 首发博客地址 系列文章地址 在Java中,有几种方式可以实现对某个变量的锁定 ...
- [转帖]SPEC CPU 2017 单线程整数性能测试与总结 (2022)
https://zhuanlan.zhihu.com/p/574105237 x86处理器的整数性能在过去4年间取得了长足的进步 x86处理器移动端性能缩水非常严重 ARM公版的旗舰级处理器相比前代进 ...
- [转帖]Jmeter笔记:使用Jmeter向kafka发送消息
https://www.cnblogs.com/daydayup-lin/p/14124816.html 日常工作中有时候需要向kafka中发送消息来测试功能或者性能,这时候我们怎么办呢?我之前是自己 ...
- [转帖]SpringBoot配置SSL 坑点总结【密码验证失败、连接不安全】
文章目录 前言 1.证书绑定问题 2.证书和密码不匹配 3.yaml配置文件问题 3.1 解密类型和证书类型是相关的 3.2 配置文件参数混淆 后记 前言 在SpringBoot服务中配置ssl,无非 ...
- [转帖]Linux小知识:sudo su和su的区别
https://www.cnblogs.com/jiading/p/11717388.html su是申请切换root用户,需要申请root用户密码.有些Linux发行版,例如ubuntu,默认没有设 ...
- STM32CubeMX教程25 PWR 电源管理 - 睡眠、停止和待机模式
1.准备材料 开发板(正点原子stm32f407探索者开发板V2.4) STM32CubeMX软件(Version 6.10.0) 野火DAP仿真器 keil µVision5 IDE(MDK-Arm ...
- Ant Design Vue中TreeSelect详解
<template> <a-tree-select v-model:value="value" style="width: 320px" :t ...