当前位置: 首页 > wzjs >正文

网站如何做传输网盘天津做网站的网络公司

网站如何做传输网盘,天津做网站的网络公司,海淘哪些网站做攻略好,百度app制作数组如下: [5,7,7,8,8,10] 问题&#xff1a; 返回有序数组中第一个>8的数的位置,如果所有数都<8,返回数组长度 暴力做法: 遍历每个数, 询问它是否>8 &#xff1f;显然时间复杂度是O(n) 高效做法: L和R分别指向询问的左右边界&#xff0c;即闭区间[L,R]&#xff0…

数组如下:

[5,7,7,8,8,10]

问题:

返回有序数组中第一个>=8的数的位置,如果所有数都<8,返回数组长度

暴力做法:

遍历每个数, 询问它是否>=8 ?显然时间复杂度是O(n)

高效做法:

L和R分别指向询问的左右边界,即闭区间[L,R],M指向当前正在询问的数 (L=0, R=n-1)

5 7 7 8 8 10
L   M      R

观察上图我们很容易得出以下两个结论:

  1. 如果当前数是小于8, 由于数组是有序的, 那么当前数和当前数左边的所有数, 都是<8的
  2. 如果当前数是大于等于8, 由于数组是有序的, 那么当前数和当前数右边的所有数, 都是>=8的
如果当前数组长度是偶数的话,中间那个数的下标为(L+R)/2,
由于C++/JAVA中"/"是下取整的,所以此时的中位数是中间靠左的那个数
如果当前数组长度是奇数的话,中间那个数的下标为(L+R)/2,此时就是正中间的那个数

 第二次查询->将L更新为M+1的位置

5 7 7 8 8 10L M  R
对于为啥不能将L更新为M?
这是因为我们每时每刻都是在闭区间上进行处理的,如果把L改成M,那就是左开右闭区间了.
当数组中只有一个元素时,8
L,R
你把R更新成M,那不就死循环了吗
因为arr[4]=8>=8,所以继续执行第三次查询

 第三次查询->将R更新M-1

5 7 7 8 8 10LR
arr((L+R)/2)>=8

 第三次查询->将R更新M-1

5 7 7 8 8 10R L
其实我们不难看出,在循环过程中,L左侧的数都是<8的,R右侧的数都是>=8的
循环不变量: L-1始终是<8,R+1始终是>=8
所以在循环结束时,R+1是我们要找的答案,由于循环结束后R+1=L,所以答案也可以用L表示

题目:在排序数组中查找元素的第一个和最后一个位置

原题链接:34. 在排序数组中查找元素的第一个和最后一个位置 - 力扣(LeetCode)

题目描述: 给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。

如果数组中不存在目标值 target,返回 [-1, -1]。

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

示例 1:

输入:nums = [5,7,7,8,8,10], target = 8

输出:[3,4]

示例 2:

输入:nums = [5,7,7,8,8,10], target = 6

输出:[-1,-1]

示例 3:

输入:nums = [], target = 0

输出:[-1,-1]

按上述的思路实现(闭区间)
int lower_bound(vector<int>& nums,int target){int left=0; int right=nums.size()-1;while(left<=right){int mid=left+(right-left)/2;if(nums[mid]<target){left=mid+1;}else{right=mid-1;} }return right+1; //return left
}
左闭右开区间的写法
5 7 7 8 8 10
L            R
此时右边界初始为6
此时上述的第三次查询,更新R=M-1时,就可以修改成R=M了
5 7 7 8 8 10LR
此时循环的截止条件就变为left<right,同时left==right时截止
int lower_bound2(vector<int>&nums,int target){int left=0; int right=nums.size();while(left<right){int mid=left+(right-left)/2;if(nums[mid]<target){left=mid+1;   //[mid+1,right]}else{right=mid;    //[left,mid)}}return left;  //循环结束时,left==right
}
开区间的写法5 7 7 8 8 10L            R
L和R分别初始化为-1和65 7 7 8 8 10
L    M       R
第一次查询后,L更新为M5 7 7 8 8 10
L    M   M1   R
第二次查询后,R更新到M1
同时最后终止条件就变成了
5 7 7 8 8 10L R   
此时(L,R)内就没有任何元素了
所以最后R就是指向答案的
终止条件的话,L+1=R
//开区间的写法
int lower_bound3(vector<int> &nums, int target) {int left = -1, right = nums.size(); // 开区间 (left, right)while (left + 1 < right) { // 区间不为空int mid = left + (right - left) / 2;if (nums[mid] < target) {left = mid; // 范围缩小到 (mid, right)} else {right = mid; // 范围缩小到 (left, mid)}// 也可以这样写// (nums[mid] < target ? left : right) = mid;}return right;
}
补充: 原问题是返回有序数组中第一个>=8的数的位置,如果问题改成>8/<8/<=8,那该如何解决呢?
">" 可以看成找>=8+1=9 的情况
"<" 可以看成找>=8左边那个数 的情况 => 找到>=8的索引然后减1
"<=" 可以看成找>8左边那个数 的情况 => 找到>8的索引然后减1
以上就是所有在有序数组中进行二分查找的情况

最后我们来解决上述题目

class Solution {
public://闭区间的写法int lower_bound(vector<int>& nums,int target){int left=0; int right=nums.size()-1;while(left<=right){int mid=left+(right-left)/2;if(nums[mid]<target){left=mid+1;}else{right=mid-1;} }return right+1;}//开区间的写法int lower_bound3(vector<int> &nums, int target) {int left = -1, right = nums.size(); // 开区间 (left, right)while (left + 1 < right) { // 区间不为空// 循环不变量:// nums[left] < target// nums[right] >= targetint mid = left + (right - left) / 2;if (nums[mid] < target) {left = mid; // 范围缩小到 (mid, right)} else {right = mid; // 范围缩小到 (left, mid)}// 也可以这样写// (nums[mid] < target ? left : right) = mid;}return right;}//[A,B) 区间的写法int lower_bound2(vector<int>&nums,int target){int left=0; int right=nums.size();while(left<right){int mid=left+(right-left)/2;if(nums[mid]<target){left=mid+1;   //[mid+1,right]}else{right=mid;    //[left,mid)}}return left;  //循环结束时,left==right}vector<int> searchRange(vector<int>& nums, int target) {int start=lower_bound(nums,target);if(start==nums.size()||nums[start]!=target){return {-1,-1};     //nums数组中没有target}//如果start 存在,那么end必定存在int end=lower_bound(nums,target+1)-1;return {start,end};}
};
start=nums.size()是left不断向右进行移动,当L=R+1,L>R终止,R其实是一直都没有移动
例子如下:
1 2 3 4 5 6 7 找>=8的数
start返回的是>=target的位置,end返回的是<=target+1的位置
根据上面提到的,<=target的情况,可以转换成找>=target+1,即lower_bound(nums,target+1), 最后再-1,就为lower_bound(nums,target+1)-1

时间复杂度的计算

每次折半就代表了一次查询,假设我们经过k次找到目标元素,n代表nums数组中元素的个数,所以n/pow(2,k)=1,k=logn

 

http://www.dtcms.com/wzjs/137142.html

相关文章:

  • 工程机械外贸网站建设营销型网站建设模板
  • 如何 做网站网站大全
  • 做电器哪个网站好郑州本地seo顾问
  • 网站开发7个基本流程成人大学报名官网入口
  • 网站建设的域名注册中国公关公司前十名
  • 网站开发款计入什么科目周口网络推广公司
  • 贵阳网站制作cncolour企业营销策划是做什么的
  • 奉贤庄行网站建设加盟教育培训哪个好
  • 网站建设定制设计人民网舆情数据中心官网
  • 做国外服务器网站百度问问我要提问
  • 中山外贸出口网站建设多少钱哪里有做企业推广
  • 网站描述范例服务营销策略
  • 成人大专咨询整站优化排名
  • 网站建设甲方原因造成停工汕头seo
  • 电子商务网站营销方案免费正规大数据查询平台
  • 济南做公司网站人工智能教育培训机构排名
  • 哪里有做网站的教程识图搜索在线 照片识别
  • 常见的网站空间今日最新新闻重大事件
  • 网站权重如何做淄博搜索引擎优化
  • 外贸seo网站重庆森林电影
  • 做神马网站优化快速排电商网站有哪些
  • 承德网站建设费用宁夏百度推广代理商
  • wordpress换中文北京自动seo
  • 做网站正规公司中国工商业联合会
  • 兰州网站制作公司服务电话新闻今日要闻
  • 外网专门做钙片的网站谷歌seo推广培训班
  • 制作网站的软件手机版百度站长收录
  • 关于做真实的自己视频网站廊坊网络推广公司
  • 河北沧州网站建设最新足球赛事
  • 建设电商网站的个人网站的制作