LeetCode第81题搜索旋转排序数组 II

简介: 文章讲解了LeetCode第81题"搜索旋转排序数组 II"的解法,通过二分查找算法并加入去重逻辑来解决在旋转且含有重复元素的数组中搜索特定值的问题。

继续打卡算法题,今天学习的是LeetCode的第81题搜索旋转排序数组 II,这道题目是道中等题。算法题的一些解题思路和技巧真的非常巧妙,每天看一看算法题和解题思路,我相信对我们的编码思维和编码能力有一些提升。

image.png

分析一波题目

本题目是LeetCode第33题搜索旋转排序数组的升级版本,本题难点在于数组中有重复数值。

第33题已经说明旋转后的有序特点。

  1. 二分中间位置mid前的数据是严格递增的,这种情况和普通的二分求解一样。看目标数据在不在前半部分。

比如 0,0,1,2,2,5,6,7,8 在位置4旋转之后变成了2,5,6,7,8,0,0,1,2 第一次二分后,前半部分2,5,6,7,8 是严格递增的。这种情况二分搜索就好搜索了。

  1. 二分中间位置mid前的数据不是严格递增的,这种情况需要看目标数据在不在后半部分。后半部分是有序的。

再比如 比如 0,0,1,2,2,5,6,7,8 在位置6旋转变成了6,7,8,0,0,1,2,2,5 这样第一次二分后,前半部分 6,7,8,0,0是分两个阶段的,但是后半半部分1,2,2,5 是有序的。

而本题是数组中数字有重复,因此我们只要在33题的基础上加上去重就可以解决了。

本题解题技巧

1、二分法是搜索有序数组的,借助旋转后的特点,二分法同样可以搜索。本题需要注意去重逻辑

编码解决


class Solution {
   
   
    public boolean search(int[] nums, int target) {
   
   
        int n = nums.length;
        if (n == 0) {
   
   
            return false;
        }
        if (n == 1) {
   
   
            return nums[0] == target ? true : false;
        }
        int l = 0, r = n - 1;
        while (l <= r) {
   
   
            int mid = (l + r) / 2;
            if (nums[mid] == target) return true;
            //相同的数,去重
            if (nums[l] == nums[mid] && nums[mid] == nums[r]) {
   
   
                ++l;
                --r;
            } else if (nums[l] <= nums[mid]) {
   
    //左边是严格递增的
                //数据在左边
                if (nums[l] <= target && target < nums[mid]) {
   
   
                    r = mid - 1;
                } else {
   
   
                //数据在右边
                    l = mid + 1;
                }
            } else {
   
   
                //数据在右边
                if (nums[mid] < target && target <= nums[n - 1]) {
   
   
                    l = mid + 1;
                } else {
   
   
                //数据在左边
                    r = mid - 1;
                }
            }
        }
        return false;
    }
}

总结

1、本题的关键是理解两个旋转有序数组后的特点。

I. 二分中间位置mid前的数据是严格递增的,这种情况和普通的二分求解一样。看目标数据在不在前半部分。

II. 二分中间位置mid前的数据不是严格递增的,这种情况需要看目标数据在不在后半部分。

相关文章
|
2月前
|
算法
LeetCode第53题最大子数组和
LeetCode第53题"最大子数组和"的解题方法,利用动态规划思想,通过一次遍历数组,维护到当前元素为止的最大子数组和,有效避免了复杂度更高的暴力解法。
LeetCode第53题最大子数组和
|
2月前
|
算法
LeetCode第74题搜索二维矩阵
文章讲解了LeetCode第74题"搜索二维矩阵"的解决方案,利用二分搜索法将问题简化,并通过数学转换找到二维矩阵中的对应元素,展示了将二维问题转化为一维问题的解题技巧。
LeetCode第74题搜索二维矩阵
|
2月前
|
算法
LeetCode第35题搜索插入位置
这篇文章介绍了LeetCode第35题"搜索插入位置"的解题方法,通过使用二分查找法,高效地找到在有序数组中插入一个目标数的最佳位置。
LeetCode第35题搜索插入位置
|
2月前
|
算法 索引
LeetCode第34题在排序数组中查找元素的第一个和最后一个位置
这篇文章介绍了LeetCode第34题"在排序数组中查找元素的第一个和最后一个位置"的解题方法,通过使用双指针法从数组两端向中间同时查找目标值,有效地找到了目标值的首次和最后一次出现的索引位置。
LeetCode第34题在排序数组中查找元素的第一个和最后一个位置
|
2月前
|
算法
LeetCode第33题搜索旋转排序数组
这篇文章介绍了LeetCode第33题"搜索旋转排序数组"的解题方法,通过使用二分查找法并根据数组的有序性质调整搜索范围,实现了时间复杂度为O(log n)的高效搜索算法。
LeetCode第33题搜索旋转排序数组
|
5天前
|
Unix Shell Linux
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
本文提供了几个Linux shell脚本编程问题的解决方案,包括转置文件内容、统计词频、验证有效电话号码和提取文件的第十行,每个问题都给出了至少一种实现方法。
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
|
2月前
|
Python
【Leetcode刷题Python】剑指 Offer 32 - III. 从上到下打印二叉树 III
本文介绍了两种Python实现方法,用于按照之字形顺序打印二叉树的层次遍历结果,实现了在奇数层正序、偶数层反序打印节点的功能。
44 6
|
2月前
|
搜索推荐 索引 Python
【Leetcode刷题Python】牛客. 数组中未出现的最小正整数
本文介绍了牛客网题目"数组中未出现的最小正整数"的解法,提供了一种满足O(n)时间复杂度和O(1)空间复杂度要求的原地排序算法,并给出了Python实现代码。
82 2
|
5天前
|
数据采集 负载均衡 安全
LeetCode刷题 多线程编程九则 | 1188. 设计有限阻塞队列 1242. 多线程网页爬虫 1279. 红绿灯路口
本文提供了多个多线程编程问题的解决方案,包括设计有限阻塞队列、多线程网页爬虫、红绿灯路口等,每个问题都给出了至少一种实现方法,涵盖了互斥锁、条件变量、信号量等线程同步机制的使用。
LeetCode刷题 多线程编程九则 | 1188. 设计有限阻塞队列 1242. 多线程网页爬虫 1279. 红绿灯路口
|
2月前
|
索引 Python
【Leetcode刷题Python】从列表list中创建一颗二叉树
本文介绍了如何使用Python递归函数从列表中创建二叉树,其中每个节点的左右子节点索引分别是当前节点索引的2倍加1和2倍加2。
38 7