当前位置:网站首页>每日一题-二分法
每日一题-二分法
2022-08-05 05:17:00 【菜鸡程序媛】
目录
搜索旋转排序数组
- 2022.07.25
- 题目
整数数组 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,5,6,7] 在下标 3 处境旋转后可能变为 [4,5,6,7,0,1,2] 。给你 旋转后 的数组 nums 和一个整数 target ,如果 nums 中存在这个目标值 target ,则返回它的下标,否则返回 -1 。
你必须设计一个时间复杂度为 O(log n) 的算法解决此问题。
- 思路
- 通过要求的时间复杂度倒推,即二分法。二分法的前提是什么?当然是要求数组是排好顺序的
- 数组是从某个位置旋转的,如果说当前的中间位置的数字比最左面的数字大,证明左半侧是单调递增的;如果小于,证明后面是单调递增的
- 从这个角度进行切入
- 还有一个容易忽略的点就是,当数组只有或者只剩下两个数字时,需要考虑nums[mid]是否等于nums[left],因为这个时候边界就是目标值了:比如10
- 代码
public int search(int[] nums, int target) {
//logn的复杂度 二分法
if(nums == null || nums.length <= 0)
return -1;
if(target == nums[0])
return 0;
if(nums[nums.length - 1] == target)
return nums.length - 1;
int left = 0, right = nums.length - 1;
while(left <= right){
int mid = left + (right - left) / 2;
if(target == nums[mid])
return mid;
else if(nums[mid] >= nums[left]){//证明左面是递增的 这里用等号的原因是当只有两个数字的时候,比如10,如果不用等号,1或者0就会找不到
if(target >= nums[left] && target < nums[mid]){
right = mid - 1;
}else{
left = mid + 1;
}
}else{
if(target > nums[mid] && target <= nums[right]){
left = mid + 1;
}else{
right = mid - 1;
}
}
}
return -1;
}
在排序数组中查找元素的第一个和最后一个位置
- 2022.07.26
- 题目
给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。如果数组中不存在目标值 target,返回 [-1, -1]。你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。
- 思路
- 算法复杂度要求是log(n),依然是二分法
- 找到target的第一个下标和最后一个下标,当匹配到nums[mid]==target的时候,依次向前和向后找,直到对应的值不等于target
- 代码
public int[] searchRange(int[] nums, int target) {
if(nums == null || nums.length <= 0)
return new int[]{-1, -1};
if(target > nums[nums.length - 1])
return new int[]{-1, -1};
if(target < nums[0])
return new int[]{-1, -1};
int left = 0, right = nums.length - 1;
while(left <= right){
int mid = left + (right - left) / 2;
if(nums[mid] == target){
int index1 = mid, index2 = mid;
while((-- index1 >= 0) && nums[index1] == target);
while((++ index2 <= nums.length - 1) && nums[index2] == target);
// 这里是因为先执行的加和减,在结果的时候要加回去,否则会小一个以及大一个
return new int[]{index1 + 1, index2 - 1};
}else if(nums[mid] < target){
left = mid + 1;
}else{
right = mid - 1;
}
}
return new int[]{-1, -1};
}
边栏推荐
- 伪RTOS-ProroThread在CH573芯片上的移植
- 【Multisim仿真】直流稳压电源设计报告
- It turns out that the MAE proposed by He Yuming is still a kind of data enhancement
- 表情捕捉的指标/图像的无参考质量评价
- 【shell编程】第二章:条件测试语句
- 电子产品量产工具(5)- 页面系统实现
- Tensorflow steps on the pit notes and records various errors and solutions
- 【ts】typescript高阶:条件类型与infer
- C语言—三子棋的实现
- A deep learning code base for Xiaobai, one line of code implements 30+ attention mechanisms.
猜你喜欢
随机推荐
一个小时教你如何掌握ts基础
CVPR最佳论文得主清华黄高团队提出首篇动态网络综述
【Multisim仿真】直流稳压电源设计报告
(oj)原地移除数组中所有的元素val、删除排序数组中的重复项、合并两个有序数组
【shell编程】第二章:条件测试语句
1008 数组元素循环右移问题 (20 分)
关于存储IOPS你必须了解的概念
Detailed explanation of BroadCast Receiver (broadcast)
framebuffer应用编程及文字显示(2)
网工必用神器:网络排查工具MTR
基于STM32F407的WIFI通信(使用的是ESP8266模块)
【nodejs】第一章:nodejs架构
【ts】typescript高阶:映射类型与keyof
「实用」运维新手一定不能错过的17 个技巧
1004 成绩排名 (20 分)
LeetCode刷题之第416题
物联网:LoRa无线通信技术
LeetCode刷题之第701题
ECCV2022 | RU&谷歌提出用CLIP进行zero-shot目标检测!
盘点关于发顶会顶刊论文,你需要知道写作上的这些事情!