33. 搜索旋转排序数组

二分查找

在每一步中根据数组的特点来确定目标元素可能存在的区间,并不断更新左右指针,缩小查找范围,直到找到目标元素或确定目标元素不存在。

1.数组原本是升序的
2.旋转后变成两个升序的数组
3.找到旋转后数组的target元素的下标

具体步骤如下:

  1. 初始化左右指针,左指针指向数组第一个元素,右指针指向数组最后一个元素。
  2. 进入循环,判断左指针是否小于等于右指针:
    • 计算中间位置的索引。
    • 如果中间位置的元素等于目标元素,返回中间位置的索引。
    • 如果左边是连续递增的,判断目标元素是否在左边递增的范围内:
      • 如果是,更新右指针为mid-1,缩小查找范围为左边部分。
      • 如果不是,更新左指针为mid+1,缩小查找范围为右边部分。
    • 如果右边是连续递增的,判断目标元素是否在右边递增的范围内:
      • 如果是,更新左指针为mid+1,缩小查找范围为右边部分。
      • 如果不是,更新右指针为mid-1,缩小查找范围为左边部分。
  3. 循环结束后仍未找到目标元素,返回-1。

时间复杂度:该算法的时间复杂度为O(log n),其中n是数组的长度。每次循环将查找范围缩小一半,因此时间复杂度为对数级别。

空间复杂度:该算法的空间复杂度为O(1),只需要常数级别的额外空间。

func main (){
	nums:=[]int{4,5,6,7,0,1,2}
	ans:=search(nums,3)
	fmt.Println(ans)
}
func search(nums []int, target int) int { //定义一个函数,接受一个整数数组和一个整数作为参数,返回一个整数
	left, right := 0, len(nums)-1 //初始化左右指针,左指针指向数组第一个元素,右指针指向数组最后一个元素
	for left <= right { //循环条件:左指针小于等于右指针
		mid := (right-left)/2 + left //计算中间位置的索引
		if nums[mid] == target { //如果中间位置的元素等于目标元素
			return mid //返回中间位置的索引
		} else if nums[left] <= nums[mid] { //如果左边是连续递增的
			if nums[left] <= target && nums[mid] > target { //如果目标元素在左边递增的范围内
				right = mid - 1 //更新右指针
			} else { //否则
				left = mid + 1 //更新左指针
			}
		} else { //如果右边是连续递增的
			if nums[mid] < target && nums[right] >= target { //如果目标元素在右边递增的范围内
				left = mid + 1 //更新左指针
			} else { //否则
				right = mid - 1 //更新右指针
			}
		}
	}
	return -1 //循环结束后仍未找到目标元素,返回-1
}


//时间复杂度:O(logn)
//空间复杂度:O(1)

你可能感兴趣的:(算法,c++,开发语言)