题目

两个有序数组长度为N,找到第N、N+1大的数

思路1:双指针,O(N)复杂度

简述思路:
如果当前A指针指向的数组A的内容小于B指针指向的数组B的内容,那么A指针往右移动,然后nums(当前已经遍历过的数字个数)也加一。
如果此时已经遍历过的数字个数等于N那么九江移动之前的A指针指向的A数组的内容送入result。
其他情况,以相反的逻辑进行。

//双指针法求解
vector<int> GetMid_On(vector<int>& A, vector<int>& B, int N)
{int A_index = 0;int B_index = 0;int nums = 0;vector<int> result;while (A_index < N && B_index < N){if (A[A_index] < B[B_index]){A_index++;nums++;if (nums == N){result.push_back(A[A_index - 1]);}if (nums == N + 1){result.push_back(A[A_index - 1]);return result;}}else {B_index++;nums++;if (nums == N){result.push_back(B[B_index - 1]);}if (nums == N + 1){result.push_back(B[B_index - 1]);return result;}}//如果两个元素相同}return result;
}int main()
{vector<int> A = { 2,4,5,6,9 };vector<int> B = { 1,3,7,8,10 };vector<int> result = GetMid_On(A, B, 5);cout << result[0] << endl;cout << result[1] << endl;cout << "结束" << endl;return 0;
}

思路2:迭代法二分

简述思路:
先初始化ab数组的start,end,mid;
然后比较各自mid指向的值的大小。
如果A[a_mid] > B[b_mid],说明,第N大的值在A数组a_mid的左边,在B数组b_mid的右边,所以对a_end以及b_start做出更新:
长度为奇数的时候,正好
a_end = a_mid;
b_start = b_mid;
当然还要考虑到长度为偶数的情况:
a_end = a_mid;
b_start = b_mid + 1;
这里只是对start进行修改,对于end值不需要修改。可以举例:
A = {2,4,6,8};
B= {1,3,5,7};
a_start = 0,a_end = 3
b_start = 0,b_end = 3
a_mid = b_mid = 3/2 =1;
A[a_mid] > B[b_mid] ,并且,长度为偶数,所以
a_end = a_mid =1;
b_start = b_mid +1 =2;
所以A被分割为:{2,4};
B被分割为:{5,7};
a_start = 0,a_end = 1
b_start = 2,b_end = 3
a_mid = 1/2 =0;
b_mid = (2+3)/2= 2;
A[a_mid] < B[b_mid] ,并且,长度为偶数,所以
a_start = a_mid =1;
b_end = b_mid =2;
此时达成a_start == a_end || b_start == b_end条件,所以可以判断两个start的值的大小,取较小值可得到第N大的数:

//迭代二分法去解
vector<int> GetMid(vector<int>& A, vector<int>& B, int N)
{vector<int> result;int a_start = 0, a_end = N - 1;int b_start = 0, b_end = N - 1;//初始化中间位置int a_mid = (a_start + a_end) / 2;int b_mid = (b_start + b_end) / 2;//循环结束条件:当数组起始点与结束点重合的时候,说明存在第N大的数while (a_start != a_end || b_start != b_end){//更新中间坐标a_mid = (a_start + a_end) / 2;b_mid = (b_start + b_end) / 2;//如果此时的A中位数与B的中位数相同,说明两个都是第N大的数if (A[a_mid] == B[b_mid]){result.push_back(A[a_mid]);result.push_back(A[a_mid] > B[b_mid] ? B[b_mid]: A[a_mid]);return result;}//如果A的中位数>B的中位数,说明此时第N大的数在A的左边,B的右边,所以需要更新a_end以及b_startelse if (A[a_mid] > B[b_mid]){//如果当前a_start-a_end之间的长度为偶数,那么中间值就是midif ((a_start + a_end) % 2 == 0){a_end = a_mid;b_start = b_mid;}else{a_end = a_mid;b_start = b_mid + 1;}}//如果A的中位数<B的中位数,说明此时第N大的数在A的右边,B的左边,所以需要更新a_start以及b_endelse{//如果当前a_start-a_end之间的长度为奇数,那么中间值就是midif ((a_start + a_end) % 2 == 0){a_start = a_mid;b_end = b_mid;}//如果当前a_start-a_end之间的长度为偶数,那么中间值就是mid+1else{a_start = a_mid + 1;b_end = b_mid;}}}//判断两个start的值的大小if (A[a_start] > B[b_start]){result.push_back(B[b_start]);if (b_start + 1 < N){if (A[a_start] > B[b_start + 1])result.push_back(B[b_start + 1]);elseresult.push_back(A[a_start]);}elseresult.push_back(A[a_start]);}else{result.push_back(A[a_start]);if (a_start + 1 < N){if (A[a_start + 1] <= B[b_start])result.push_back(A[a_start + 1]);elseresult.push_back(B[b_start]);}elseresult.push_back(B[b_start]);}return result;
}int main()
{vector<int> A = { 2,4,5,6,9 };vector<int> B = { 2,4,5,6,9 };//vector<int> B = { 1,3,7,8,10 };vector<int> result = GetMid(A, B, 5);for(int i = 0;i < result.size();i++)cout << result[i] << endl;cout << "结束" << endl;return 0;
}

思路3:递归法二分

写完迭代法之后,递归将a_start,a_end,b_start,b_end,作为递归函数的参数放入。递归函数的一开始写终止条件,参考迭代法。
终止条件后面,写根据中间值的大小,对a_start,a_end,b_start,b_end进行不同赋值,达到分割数组的目的。

//递归二分法求解
vector<int> GetMid(vector<int>& A, vector<int>& B, int a_start,int a_end,int b_start,int b_end,int N)
{vector<int> result;//初始化中间位置int a_mid = (a_start + a_end) / 2;int b_mid = (b_start + b_end) / 2;//如果有答案了if (A[a_mid] == B[b_mid]){result.push_back(A[a_mid]);result.push_back(A[a_mid] > B[b_mid] ? B[b_mid] : A[a_mid]);return result;}if (a_start == a_end || b_start == b_end){//判断两个start的值的大小if (A[a_start] > B[b_start]){result.push_back(B[b_start]);if (b_start + 1 < N){if (A[a_start] > B[b_start + 1])result.push_back(B[b_start + 1]);elseresult.push_back(A[a_start]);}elseresult.push_back(A[a_start]);}else{result.push_back(A[a_start]);if (a_start + 1 < N){if (A[a_start + 1] <= B[b_start])result.push_back(A[a_start + 1]);elseresult.push_back(B[b_start]);}elseresult.push_back(B[b_start]);}return result;}//递归更新边界值if (A[a_mid] > B[b_mid]){//如果当前a_start-a_end之间的长度为偶数,那么中间值就是midif ((a_start + a_end) % 2 == 0){return GetMid(A, B, a_start, a_mid, b_mid, b_end, N);}else{return GetMid(A, B, a_start, a_mid, b_mid + 1, b_end, N);}}//如果A的中位数<B的中位数,说明此时第N大的数在A的右边,B的左边,所以需要更新a_start以及b_endelse{//如果当前a_start-a_end之间的长度为偶数,那么中间值就是midif ((a_start + a_end) % 2 == 0){return GetMid(A, B, a_mid, a_end, b_start, b_mid, N);}else{return GetMid(A, B, a_mid + 1, a_end, b_start, b_mid, N);}}
}int main()
{vector<int> A = { 2,4,5,6,9 };//vector<int> B = { 2,4,5,6,9 };int N = A.size();vector<int> B = { 1,3,7,8,10 };vector<int> result = GetMid(A, B, 0, N-1,0,N-1,N);for(int i = 0;i < result.size();i++)cout << result[i] << endl;cout << "结束" << endl;return 0;
}

二分法:两个有序数组长度为N,找到第N、N+1大的数相关推荐

  1. 数组越界怎么判断_算法连载之求解两个有序数组的中位数

    问题 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2.找出这两个有序数组的中位数.假设 nums1 和 nums2 不会同时为空. 示例 1: nums1 = [1, 3] num ...

  2. LeetCode4寻找两个有序数组的中位数(二分查找+分治)

    目录 1.题目 2.分析 3.代码 二分查找:绝大多数二分查找问题利用的是单调性,也有一些例外)或者题目本身蕴含的可以逐渐缩小问题规模的特性解决问题.时间复杂度log级. 分治法的设计思想是:将一个难 ...

  3. [二分法]leetcode4:寻找两个有序数组的中位数(hard)

    题目: 题解: 又是一道hard题啊,这对于原来就很少做hard的我来说,可以说是很锻炼人了,坐下来静心思考,拿纸笔画结果,写推导过程,终于把这道题搞定了. 思路: 二分法,中位数就是将数组划分为长度 ...

  4. 两个有序数组A、B,长度分别为m、n,找到两个数组的第k个值并返回

    /*************************************************************************** **description:两个有序数组A.B ...

  5. LeetCode实战:寻找两个有序数组的中位数

    题目英文 There are two sorted arrays nums1 and nums2 of size m and n respectively. Find the median of th ...

  6. 6 js 比较两个数组的差异_每天一道算法题(js)(3)——寻找两个有序数组的中位数...

    给定两个大小为 m 和 n 的有序数组 nums1 和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)). 你可以假设 nums1 和 nums2 ...

  7. leetcode 4. 寻找两个有序数组的中位数,c语言

    leetcode上第四道题,如下. 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2.请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)).你可以假 ...

  8. C++leetcode找出两个有序数组的中位数(2)

    给定两个大小为 m 和 n 的有序数组 nums1 和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)). 如果不考虑复杂度的话这个题目很简单:将两 ...

  9. LeetCode 4. 寻找两个有序数组的中位数(二分查找,难)

    文章目录 1. 题目 2. 解题 2.1 合并数组 2.2 优化2.1解法,双指针 2.3 二分法(找第k个数) 2.4 切分法 1. 题目 给定两个大小为 m 和 n 的有序数组 nums1 和 n ...

最新文章

  1. 面试精讲之面试考点及大厂真题 - 分布式专栏 13项目中为什么要使用消息队列
  2. 剑指Offer09-用两个栈实现队列
  3. XPath匹配标签使用text()判断获取结果失败/为空的问题及解决方法
  4. 贺利坚老师汇编课程32笔记:处理字符串——大小写转换通过与和或运算加减20H
  5. Exchange 2016 之删除与恢复用户邮箱
  6. Android-广播
  7. 软件开发技术文档编写规范_在软件开发中编写技术文档
  8. vue点击按钮跳转页面
  9. 如何在Mac上自定义文件和文件夹图标?看这里
  10. 云计算会不会被边缘计算取而代之
  11. 6种交互式内容创意帮助跨境电商卖家提高独立站商店知名度
  12. 用php实现成绩管理系统,PHP成绩管理系统 PHP简单操作 学生成绩管理 成绩管理源码 三张表...
  13. shell+ftp+中文乱码_linux系统(本例为Centos)ftp上传中文名文件乱码或者显示问号解决方法 - 老牛博客...
  14. 第十二周 任务二
  15. SharePoint Server 2007 简体中文下载
  16. 做为站长眼光要放在远方
  17. 一、saturn快速启动
  18. 建立APICloud云端数据库
  19. 什么是软件兼容性测试,怎么分类,做兼容性测试的测试机构有哪些?
  20. Yammer取消了对Scala的立场

热门文章

  1. 大学4年毕业后我是如何还清的助学贷款。
  2. 新版本阿里云网站的云服务器添加安全组规则
  3. android 二次绘制 layout,View的三次measure,两次layout和一次draw
  4. linux动态库ppt,LINUX系统中动态链接库创建与使用补充_区块链白皮书代写|市场计划书项目PPT设计_Tbleg...
  5. python图标icon_用Python提取exe图标icon
  6. 华为硬件工程师社招机考题库_干货:2016年华为中兴硬件工程师笔试题目与经验...
  7. antd listView中onEndReached()失效
  8. 页面重构-让我们的布局自适应
  9. 网站大流量高并发访问的处理解决办法
  10. python链表的实现,有注释