首页 > 其他分享 >LeetCode题练习与总结:搜索旋转排序数组

LeetCode题练习与总结:搜索旋转排序数组

时间:2024-03-14 21:02:24浏览次数:23  
标签:right target nums mid 数组 排序 LeetCode left

一、题目

整数数组 nums 按升序排列,数组中的值 互不相同

在传递给函数之前,nums 在预先未知的某个下标 k0 <= k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2]

给你 旋转后 的数组 nums 和一个整数 target ,如果 nums 中存在这个目标值 target ,则返回它的下标,否则返回 -1 。

你必须设计一个时间复杂度为 O(log n) 的算法解决此问题。

二、解题思路

  1. 初始化两个指针,leftright,分别指向数组的开始和结束。
  2. left 小于 right 时,执行以下步骤: a. 计算中间位置 mid。 b. 如果 nums[mid] 等于 target,则返回 mid。 c. 判断 nums[left]nums[mid] 之间的值是否有序:
    • 如果有序,说明 target 必须在 leftmid 之间,更新 rightmid - 1
    • 如果无序,说明 target 必须在 midright 之间,更新 leftmid + 1
  3. 如果循环结束还没有找到 target,则返回 -1

三、具体代码

class Solution {
    public int search(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;
        
        while (left < right) {
            int mid = left + (right - left) / 2;
            
            // 如果找到了目标值
            if (nums[mid] == target) {
                return mid;
            }
            
            // 判断左右两边哪一边是有序的
            if (nums[left] <= nums[mid]) {
                // 左边有序,target 在左边
                if (nums[left] <= target && target < nums[mid]) {
                    right = mid - 1;
                } else {
                    left = mid + 1;
                }
            } else {
                // 右边有序,target 在右边
                if (nums[mid] < target && target <= nums[right]) {
                    left = mid + 1;
                } else {
                    right = mid - 1;
                }
            }
        }
        
        // 循环结束,如果 left 等于 right 且 nums[left] 等于 target,则返回 left
        // 否则返回 -1
        return nums[left] == target ? left : -1;
    }
}

四、时间复杂度和空间复杂度

1. 时间复杂度
  • 时间复杂度是 O(log n)。
  • 这是因为在每次迭代中,搜索范围都会减半。
  • 这是二分查找算法的典型特征,其中 n 是数组的长度。
  • 在最坏的情况下,需要进行 log(n) 次迭代才能找到目标值或确定目标值不存在。
2. 空间复杂度
  • 空间复杂度是 O(1)。
  • 这个算法是原地进行的,不需要额外的存储空间。
  • 所有的计算都是在常量级别的额外空间内完成的,例如使用几个辅助变量(left, right, mid)。
  • 这些变量的数量不随着输入数据的规模变化,因此空间复杂度是常数级别的。

五、总结知识点

1. 二分查找算法(Binary Search):

  • 这是一种在有序数组中查找特定元素的高效算法。
  • 通过不断将搜索范围减半,二分查找可以在对数时间内找到目标值或确定目标值不存在。

2. 旋转排序数组的处理:

  • 由于数组是旋转过的,它不再是完全有序的,这就需要在二分查找的基础上进行调整。
  • 通过比较数组的两端(leftright)以及中间点(mid)的值,可以确定哪一半是有序的,并据此调整搜索范围。

3. 条件判断和循环控制:

  • 使用 while 循环来重复执行二分查找的过程,直到找到目标值或搜索范围为空。
  • 使用 ifelse 语句来判断数组的哪一半是有序的,并据此更新搜索范围的边界。

4. 数组索引的更新:

  • 根据中间点 mid 的值与目标值 target 的关系,以及数组的有序性,更新 leftright 的值。

5. 返回值的处理:

  • 如果在循环结束后 leftright 相遇,并且 nums[left] 等于 target,则返回 left
  • 如果 leftright 相遇,但 nums[left] 不等于 target,则返回 -1 表示目标值不存在于数组中。

6. 防止整数溢出:

  • 在计算 mid 时,使用 left + (right - left) / 2 而不是 (left + right) / 2 来避免可能的整数溢出问题。

以上就是解决这个问题的详细步骤,希望能够为各位提供启发和帮助。

标签:right,target,nums,mid,数组,排序,LeetCode,left
From: https://blog.csdn.net/weixin_62860386/article/details/136427852

相关文章

  • 数组练习-小习题
    多个字符从两端开始移动,向中间汇聚输出,例如:打印Hello,word!第一个打印出来H(左一),然后打印!(右一),接着e(右二),下面是d(左二).......依次打印,这里介绍一个关键字:strlen(),用来测量字符串的长度,注意字符串如果带有"\0",strlen是不计算\0的,只计算\0之前的字符数。system(“cls”):清理屏幕。#i......
  • LeetCode题练习与总结:在排序数组中查找元素的第一个和最后一个位置
    一、题目给你一个按照非递减顺序排列的整数数组nums,和一个目标值target。请你找出给定目标值在数组中的开始位置和结束位置。如果数组中不存在目标值target,返回 [-1,-1]。你必须设计并实现时间复杂度为 O(logn) 的算法解决此问题。二、解题思路1.查找起始位置:使......
  • lc2035 将数组分成两个数组并最小化数组和的差
    给你一个长度为2n的整数数组,需要将它分成两个长度为n的数组,分别求出两个数组的和,并最小化两个数组和之差的绝对值。nums中每个元素都需要放入两个数组之一,求最小的数组和之差。1<=n<=15;-1E7<=nums[i]<=1E7直接暴搜的话最坏时间复杂度是O(2^30),会TLE,可以使用双向dfs优化,每次df......
  • day-19 合并后数组中的最大元素
    思路:从后向前遍历数组,用tans记录每一种可能的最大值,ans为实际最大值。注意:若ans==0,返回nums[0]要用longcodeclassSolution{publiclongmaxArrayValue(int[]nums){longans=0;longtans=0;booleanflag=true;for(in......
  • 『LeetCode』10. 正则表达式匹配 Regular Expression Matching
    题目描述给你一个字符串s和一个字符规律p,请你来实现一个支持'.'和'*'的正则表达式匹配。'.'匹配任意单个字符'*'匹配零个或多个前面的那一个元素所谓匹配,是要涵盖整个字符串s的,而不是部分字符串。示例1:输入:s="aa",p="a"输出:false解释:"a"无法匹配"aa"整个字......
  • C++动态数组
    #include<iostream>usingnamespacestd;intmain(){ intt,i=0,j=0; cin>>t; char*pc=nullptr;//初始化 int*pi=nullptr;//初始化 float*pf=nullptr;//初始化 intsum=0; intFLAG=0; while(FLAG<t) { charch; cin>>......
  • LeetCodeHot100 73. 矩阵置零 54. 螺旋矩阵 48. 旋转图像 240. 搜索二维矩阵 II
    73.矩阵置零https://leetcode.cn/problems/set-matrix-zeroes/description/?envType=study-plan-v2&envId=top-100-likedpublicvoidsetZeroes(int[][]matrix){inttop=0,bottom=matrix.length,left=0,right=matrix[0].length;int[][]flag......
  • Java中的Map集合如何根据key值排序?
    Java中的Map集合如何根据key值排序(HashMap<String,Object>)?Map集合的键(key)默认是按照它们的hashCode排序的,这在有时间不符合业务排序。如果你想要根据Map的key值进行排序,一般以下有几种方法可以实现。方法一:使用TreeMap使用TreeMap类,它会自动根据key的自然顺序或自定义比较器......
  • LeetCode232.栈实现队列
    ques:用两个栈实现队列功能ans:与225一样的思路,看完225大佬们的题解之后能很轻松的想出思路,用s1来实现真正模拟队列中的元素顺序,借助s2辅助完成这一排序代码实现#include<iostream>#include<stack>usingnamespacestd;classMyQueue{private:stack<int>s1;/......
  • leetcode.21 合并两个有序链表
     21.合并两个有序链表 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。  示例1:输入:l1=[1,2,4],l2=[1,3,4]输出:[1,1,2,3,4,4]示例2:输入:l1=[],l2=[]输出:[]示例3:输入:l1=[],l2=[0]输......