程序员面试金典——解题总结: 9.17中等难题 17.6给定一个整数数组,编写一个函数,找出索引m和n,只要将m和n之间的元素排好序,整个数组就是有序的。注意:n - m越小越好,也就是说,找出
来源:互联网 发布:photogragh是什么软件 编辑:程序博客网 时间:2024/04/27 23:49
#include <iostream>#include <stdio.h>#include <vector>using namespace std;/*问题:给定一个整数数组,编写一个函数,找出索引m和n,只要将m和n之间的元素排好序,整个数组就是有序的。注意:n - m越小越好,也就是说,找出 符合条件的最短序列。分析:我们将数组分成3个部分,A[0... m-1],A[m ... n],A[n+1...A.length-1] 那么必定要符合如下条件:前面数组的最大值要<=中间数组的最小值,中间数组的最大值要<=后面数组的最小值 如果数组已经有序,那么m,n都设置为-1 如果数组无序,可以遍历m和n,需要不断从中间数组中取出最小值和最大值并比较,符合条件就可以 时间复杂度= 不断尝试m和n的时间O(n^2) + 从中间数组选择最小值和最大值的的时间O(n)【可以采用线性时间选择算法,具体的算法我记得好像是数组不断划分为5的等分来做】 而且需要前面数组和后面数组都要有序 输入:9(数组元素个数,接下来一行是n个元素)1 3 5 9 8 7 4 6 13131 2 4 7 10 11 7 12 6 7 16 18 19输出:2(m) 7(n)3 9书上解法:1 从左到右遍历,如果当前元素比后面元素大,记录当前元素位置low【牛逼,确定了左边有序序列】 从右到左遍历,如果当前元素比其前面元素小,记录该元素位置high 中间数组在下标low+1~high-1 寻找中间数组中最小值min,最大值max, 从low位置向前遍历,如果有元素的值 < min,记录其位置pos,则m = pos + 1, 从high位置向后遍历,如果有元素的值 > max,记录位置pos,则n= pos - 1;表明该元素前面部分都是<=max的,这是不符合题目要求的,所以设定n=pos-1 【这个解法是错误的】 例如:1 3 5 9 8 7 4 6 13, 寻找中间数组得到:[1 3 5 9] [8 7] [4 6 13] 对中间数组,确定左边中小于中间数组最小值,确定右边大于中间数组最大值,得:[1 2 5] [9 8 7 4 6] [13] 发现尽管对中间排好序,但是 5 大于 4,仍然不是有序的 如果继续对数组: [1 2 5] [9 8 7 4 6] [13]重复上述处理,找到[9 8 7 4 6]中最小值为4,最大值为9, 发现修改左边下标为2,把5包含进来,得到最终 [1 2] [5 9 8 7 4 6] [13] 结束处理的必要条件必须满足: A[beginIndex - 1] <= min ,并且A[endIndex + 1] >= max2//书上解法错误,这里必须要判断找到的下标是否真的还符合题目要求;如果不符合,需要继续寻找下标int flag = isCanFinish(datas , beginIndex , endIndex);while( 1 != flag){//如果左边大于中间数组最小值,左边寻找到的下标减1,并继续判断if( 2 == flag){beginIndex--;flag = isCanFinish(datas , beginIndex , endIndex);}else if( 3 == flag){endIndex++;flag = isCanFinish(datas , beginIndex , endIndex);}}3寻找数组 datas[low ... high]中的最小值和最大值,这里用分治法来做分治法原理:将规模为n的子问题划分为k个规模较小的子问题,子问题独立,对子问题求解,并将答案合并分治法本质是一种特殊地递归,一般可以通过二分法进行处理分治法处理步骤:1)划分 , 2)处理 ,3)归并答案如果low = high,表明只有一个元素,则最大值和最小值都是它否则,令min = datas[low],max=datas[max]; 令middle = low + (high - low)/2;得到 result1 = findMinAndMax(datas , low , middle); result2 = findMinAndMax(datas , middle+1 , high); min = result1.min < result2.min ? result1.min : result2.min; max = result1.max > result2.max ? result1.max : result2.max;*/bool isOrder(vector<int>& datas){if(datas.empty()){return true;}int size = datas.size();for(int i = 1 ; i < size ; i++){if(datas.at(i) < datas.at(i-1)){return false;}}return true;}//寻找左边递增序列的截止位置int findLeftIndex(vector<int>& datas){if(datas.empty()){return -1;}int size = datas.size();int i;for(i = 0 ; i < size - 1 ; i++){if(datas.at(i) > datas.at(i+1)){return i;}}return i;}//寻找右边递增序列的截止位置int findRightIndex(vector<int>& datas){if(datas.empty()){return -1;}int size = datas.size();int i;for(i = size - 1 ; i >= 1 ; i--){if(datas.at(i) < datas.at(i-1)){return i;}}return i;}//寻找大于或小于value的下标int findIndex(vector<int>& datas , int index , int value , bool isFindLeft){//如果是寻找左边数组中,第一个比value小的下标int i;int size = datas.size();if(isFindLeft){for(i = index ; i >= 0 ; i--){if(datas.at(i) <= value){return (i + 1);}}}else{for(i = index ; i < size ; i++ ){if(datas.at(i) >= value){return (i - 1);}}}return -1;}/*寻找数组 datas[low ... high]中的最小值和最大值,这里用分治法来做分治法原理:将规模为n的子问题划分为k个规模较小的子问题,子问题独立,对子问题求解,并将答案合并分治法本质是一种特殊地递归,一般可以通过二分法进行处理分治法处理步骤:1)划分 , 2)处理 ,3)归并答案如果low = high,表明只有一个元素,则最大值和最小值都是它否则,令min = datas[low],max=datas[max]; 令middle = low + (high - low)/2;得到 result1 = findMinAndMax(datas , low , middle); result2 = findMinAndMax(datas , middle+1 , high); min = result1.min < result2.min ? result1.min : result2.min; max = result1.max > result2.max ? result1.max : result2.max;*/pair<int , int> findMinAndMax(vector<int>& datas , int low , int high){int size = datas.size();if(datas.empty() || low > high || high >= size){pair<int, int> result(-1,-1);return result;}//如果只有一个元素if(low == high){pair<int , int> result(datas.at(low) , datas.at(low));return result;}//如果有两个元素,注意是等于号else if( high == low + 1){int min = datas.at(low) < datas.at(high) ? datas.at(low) : datas.at(high);int max = datas.at(low) > datas.at(high) ? datas.at(low) : datas.at(high);pair<int , int> result(min ,max);return result;}//多个元素,二分后递归处理{int realMin = INT_MAX;int realMax = INT_MIN;int middle = low + (high - low) / 2;pair<int , int> result1 = findMinAndMax(datas , low , middle);pair<int , int> result2 = findMinAndMax(datas , middle + 1 , high);//比较realMin = result1.first < result2.first ? result1.first : result2.first;realMax = result1.second > result2.second ? result1.second : result2.second;pair<int , int> result(realMin , realMax);return result;}}//判断当前数组是否可以结束处理,即已经找到正确的下标,返回1:表示可以正确,返回2:表示左边不正确,返回3:表示右边不正确int isCanFinish(vector<int>& datas , int beginIndex , int endIndex){if(datas.empty() || beginIndex < 0 || endIndex >= datas.size() || beginIndex >= endIndex){return 1;}pair<int , int> result = findMinAndMax(datas , beginIndex , endIndex);int min = result.first;int max = result.second;//如果左边大于中间数组最小值if(datas.at(beginIndex - 1) > min ){return 2;}//如果右边小于中间数组最大值else if(datas.at(endIndex + 1) < max){return 3;}else{return 1;}}pair<int, int> getIndexs(vector<int>& datas){pair<int , int> invalidResult(-1 , -1);if(datas.empty()){return invalidResult;}//检查数组是否有序,如果有序,直接返回if(isOrder(datas)){return invalidResult;}int leftIndex = findLeftIndex(datas);int rightIndex = findRightIndex(datas);pair<int , int> result = findMinAndMax(datas , leftIndex + 1 , rightIndex - 1);int min = result.first;int max = result.second;int beginIndex = findIndex(datas , leftIndex , min , true) ;int endIndex = findIndex(datas , rightIndex , max , false);//书上解法错误,这里必须要判断找到的下标是否真的还符合题目要求;如果不符合,需要继续寻找下标int flag = isCanFinish(datas , beginIndex , endIndex);while( 1 != flag){//如果左边大于中间数组最小值,左边寻找到的下标减1,并继续判断if( 2 == flag){beginIndex--;flag = isCanFinish(datas , beginIndex , endIndex);}else if( 3 == flag){endIndex++;flag = isCanFinish(datas , beginIndex , endIndex);}}pair<int, int> realResult(beginIndex , endIndex);return realResult;}void process(){int num;vector<int> datas;int value;pair<int, int> result;while(cin >> num){datas.clear();//复用之前容器,数据要清空for(int i = 0 ; i < num ; i++){cin >> value;datas.push_back(value);}result = getIndexs(datas);cout << result.first << " " << result.second << endl;}}int main(int argc , char* argv[]){process();getchar();return 0;}
0 0
- 程序员面试金典——解题总结: 9.17中等难题 17.6给定一个整数数组,编写一个函数,找出索引m和n,只要将m和n之间的元素排好序,整个数组就是有序的。注意:n - m越小越好,也就是说,找出
- 有一个整数数组,请编写一个函数,找出索引m和n,只要将m和n之间的元素排好序,整个数组就是有序的。注意:n-m应该越小越好,也就是说,找出符合条件的最短序列。 给定一个int数组A和数组的大小n,请
- 程序员面试金典——解题总结: 9.18高难度题 18.12给定一个正整数和负整数组成的N*M矩阵,编写代码找出元素总和最大的子矩阵。
- 程序员面试金典——解题总结: 9.18高难度题 18.3编写一个方法,从大小为n的数组中随机选出m个整数。要求每个元素被选中的概率相同。
- 程序员面试金典——解题总结: 9.17中等难题 17.12设计一个算法,找出数组中两数之和为指定值的所有整数对。
- 程序员面试金典——解题总结: 9.17中等难题 17.8给定一个整数数组(有正数有负数),找出总和最大的连续数列,并返回总和
- 45一个整数数组,长度为n,将其分为m份,使各份的和相等,求m的最大值
- 一个整数数组,长度为n,将其分为m份,使各份的和相等,求m的最大值
- 一个整数数组,长度为n,将其分为m份,使各份的和相等,求m的最大值
- 一个整数数组,长度为n,将其分为m份,使各份的和相等,求m的最大值
- 一个整数数组,长度为n,将其分为m份,使各份的和相等,求m的最大值
- 一个整数数组,长度为n,将其分为m 份,使各份的和相等,求m 的最大值
- 一个整数数组,长度为n,将其分为m份,使各份的和相等,求m的最大值
- 一个整数数组,长度为n,将其分为m份,使各份的和相等,求m的最大值
- 一个整数数组,长度为n,将其分为m 份,使各份的和相等,求m 的最大值
- 一个整数数组,长度为n,将其分为m份,使各份的和相等,求m的最大值。
- 将一个n元素的数组平均分为m分,是每组和相等,求最大m
- 【微软谷歌面试100题--【45】一个整数数组,长度为n,将其分为m 份,使各份的和相等,求m 的最大值
- oracle中exists的用法
- Eclipse导入到web项目没有run on server
- 【精品分享】C/C++框架和库
- arcgis api for js入门开发系列二不同地图服务展示(含源代码)
- python 3-5-1 关于文件的操作-open/read/readlines/seek/write/writelines
- 程序员面试金典——解题总结: 9.17中等难题 17.6给定一个整数数组,编写一个函数,找出索引m和n,只要将m和n之间的元素排好序,整个数组就是有序的。注意:n - m越小越好,也就是说,找出
- 请求数据形式XML的解析
- 如何在同一台电脑上部署多个tomcat服务器
- 今天学习了background、pre、text-indent、继承性
- arcgis api for js入门开发系列三地图工具栏(含源代码)
- match
- cocos判断中文字符
- 630C-
- 140----遍历数组