【分治】peak find
分治算法
算法设计中一种常用的优化方法就是分治的思想,它的解决思路就是将原始的问题划分为性质一样,但是规模减小的子问题,然后通过子问题的解和合并子问题的解得到最终的解,就是分治的思想;
比较常见的分治有 归并排序算法,快速排序算法,两种都是优化的排序算法;
归并排序
归并排序算法通过将问题划分为左半部分、右半部分问题的解决,然后通过合并有序的左半部分、有序的右半部分使得最终有序。所以假设问题的求解时间复杂度为 T(n) = 2*T(n/2) + C(n),其中T(n)表示长度为n的归并排序复杂度,等于两个子问题的复杂度和合并两个有序序列的复杂度C(n),C(n)代表一个关于n的常数项复杂度,最终时间复杂度nlog(n),
快速排序
快速排序的思想和归并排序的思想比较类似,随机找到一个partition把数组划分为比它小的部分,比它大的部分,然后依次使用这种思想继续划分其左半部分,右半部分,但是不能保证每次都能够将问题规模正好的切分为两个相同的,所以平均时间复杂度为nlog(n),最坏的时间复杂度为n^2(每次的patition元素选择都很糟糕)
切入正题,使用分治的两个算法题目
一维数组的局部最大值查找
题目描述:在一个整数数组中查找一个数,该数大于等于其左边的元素、并且大于等于其右边的元素(假定数组最边界是极小值,即-1,n的索引位置为Integer.MIN_VALUE)
举例:[1,2,3,4,5]则返回5, [1,3,2,4,3,5]中返回3,4,5任意一个;
思路:
逐个遍历可以查找到所有的局部最大值,但是时间复杂度O(n),题目要求找到一个即可,所以应该有优化的空间。
能够比n更优化的很容易想到二分的思路,所以顺着这个思路,首先找到mid元素,如果mid元素满足局部最大值,直接返回,不满足?
以下三种情况,此时选择最大的那一半继续二分查找即可,因为最大的那一边必定包含一个局部最大值
public int peekFind1(int[] array) {
int len = array.length;
//len == 0 exception
int l = 0, r = len - 1;
while(r > l) {
int m = l + (r - l)/2;
if( (m - 1 < 0 || array[m] >= array[m-1]) && (m + 1 >= len || array[m] >= array[m+1]) ) {
return array[m];
}
else if( (m - 1 >= 0 && array[m-1] > array[m]) ) {
r = m-1;
}
else {
l = m+1;
}
}
return array[r];
}
二维数组的局部最大值查找
题目描述:在一个二维整数数组中查找一个数,该数大于等于其上、下、左、右的元素(假定数组最边界是极小值)
思路:
逐个遍历可以查找到所有的局部最大值,但是时间复杂度O(n^2),题目要求找到一个即可,所以应该有优化的空间。
二维数组的扩展正常的思路可能会想着借助一维数组已有的解决方案去解决这个题目,但是这么想可能就会陷入死胡同,
比如针对每行使用刚才一维的解决方案,找到每行的局部最大值,好像并没有什么帮助,
在针对每列使用刚才一维的解决方案,找到每列的局部最大值,但是没办法保证与刚才每行的有重叠?
所以想利用一维的算法求出每列或者每行的最大值,此时在最大值的以为数组中使用一维的解决方案即可,但是求解每列或者每行的最大值使得问题复杂度达到O(n^2)了;
所以思路回退到分治的策略,比如先找到中间一列的最大值,这个值必定大于其上下,然后查看这个值左右的情况,如果满足局部最大值,直接返回,不满足?
同样是上面的三种情况,选择有更大元素的那半边继续采用这种思想求解即可得到答案,时间复杂度nlog(n),
图解:
public int maxNum(int[] array) {
int result = array[0];
int idx = 0;
for(int i = 1;i < array.length;i++) {
if(array[i] > result) {
result = array[i];
idx = i;
}
}
return idx;
}
public int peekFind2(int[][] matrix) {
int row = matrix.length;
//row == 0 exception
int column = matrix[0].length;
if(row == 1) return peekFind1(matrix[0]);
if(column == 1) {
int[] array = new int[row];
for(int i = 0;i < row;i++) array[i] = matrix[i][0];
return peekFind1(array);
}
int startR = 0, endR = row - 1;
while(endR > startR) {
int midR = startR + (endR - startR)/2;
int maxIdx = maxNum(matrix[midR]);
if( (midR - 1 < 0 || matrix[midR][maxIdx] >= matrix[midR - 1][maxIdx]) && (midR + 1 >= row || matrix[midR][maxIdx] >= matrix[midR + 1][maxIdx]) ) {
return matrix[midR][maxIdx];
}
else if( (midR - 1 >= 0 && matrix[midR - 1][maxIdx] > matrix[midR][maxIdx]) ) {
endR = midR - 1;
}
else {
startR = midR + 1;
}
}
return matrix[startR][maxNum(matrix[startR])];
}
针对二维的局部最大值求解存在O(n)时间复杂度的解决方案,这个后面再分享,思考算法的时候尽可能的发散思维,不能僵化住自己的思想。
如果发现上面有什么错误,欢迎指正。
【分治】peak find的更多相关文章
- Java for LeetCode 162 Find Peak Element
A peak element is an element that is greater than its neighbors. Given an input array where num[i] ≠ ...
- (leetcode162)find peak element
1题目 A peak element is an element that is greater than its neighbors. Given an input array where num[ ...
- 【Leetcode】【Medium】Find Peak Element
A peak element is an element that is greater than its neighbors. Given an input array where num[i] ≠ ...
- [bzoj2152][聪聪和可可] (点分治+概率)
Description 聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃.两个人都想玩儿电脑(可是他们家只有一台电脑)……遇到这种问题,一般情况下石头剪刀布就好 ...
- POJ 2965. The Pilots Brothers' refrigerator 枚举or爆搜or分治
The Pilots Brothers' refrigerator Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 22286 ...
- [poj1741][tree] (树/点分治)
Description Give a tree with n vertices,each edge has a length(positive integer less than 1001). Def ...
- [LeetCode] Find Peak Element 求数组的局部峰值
A peak element is an element that is greater than its neighbors. Given an input array where num[i] ≠ ...
- 【教程】简易CDQ分治教程&学习笔记
前言 辣鸡蒟蒻__stdcall终于会CDQ分治啦! CDQ分治是我们处理各类问题的重要武器.它的优势在于可以顶替复杂的高级数据结构,而且常数比较小:缺点在于必须离线操作. CDQ分治的基 ...
- LeetCode 162 Find Peak Element
Problem: A peak element is an element that is greater than its neighbors. Given an input array where ...
随机推荐
- 利用vertical-align:middle垂直居中
以前总是以为vertical-align与text-align是同样的道理,一个是垂直居中,一个是水平居中,结果在这里一点效果也没有.事实上vertical-align与text-align完全不一样 ...
- Python中的列表生成器,迭代器的理解
首先,思考一个问题,比如,我们想生成0-100的列表,我们怎么做? 当然,可以写成 list1=[1,2,3...,100] 可以看出,这种方法不适合生成长的列表,那么Python中就可以利用已有的列 ...
- 高质量PHP代码的50个实用技巧必备(下)
26. 避免直接写SQL, 抽象之 不厌其烦的写了太多如下的语句: ? 1 2 <span style="color:#333333;font-family:''Helvetica, ...
- 构建Nginx均衡LAMP高性能服务器
LNAMP(Linux+Nginx+Apache+Mysql+PHP)架构受到很多IT企业的青睐,取代了原来认为很好的LNMP(Linux+Nginx+Mysql+PHP)架构,那我们说LNAMP到底 ...
- 【luogu P1613】跑路
https://www.luogu.org/problem/show?pid=1613 看到2k就能想到倍增.用一个数组avai[i][j][k]表示点i与点j是否存在长2k的路径,则可以递推出ava ...
- windows10版本1709 在桌面和文件中点击右键,会引起卡顿
windows自动升级到1709版本后出现的问题,而之前是没有这种问题的. 最终解决办法:(需要设置注册表) 运行:快捷键Win+R regedit 路径:可直接复制后粘贴+回车 HKEY_CLASS ...
- C语言简单实现链栈基本几个功能(适合新手看,大神可指正)
接着上一次的顺序栈,今天我记一下链栈,因为我也是刚学不久,有些地方也稍稍理解不了,所以,一起共勉.我会用我自己结合教材上画的图,争取跟代码一起结合,用文字和图最大化的解释代码,这样的话 ...
- python爬虫(五)_urllib2:Get请求和Post请求
本篇将介绍urllib2的Get和Post方法,更多内容请参考:python学习指南 urllib2默认只支持HTTP/HTTPS的GET和POST方法 urllib.urlencode() urll ...
- RandomAccessFile详解
此类的实例支持对随机访问文件的读取和写入.随机访问文件的行为类似存储在文件系统中的一个大型 byte 数组.存在指向该隐含数组的光标或索引,称为文件指针:输入操作从文件指针开始读取字节,并随着对字节的 ...
- [睡前灵感and发散思维]由一个简单的数组比较问题而想到的
前言 据说,一只优秀的程序猿往往会有这样的经历,白天遇到一个绞尽脑汁也无法解决的问题,晚上睡了后,半夜在梦中会灵感涌现,立马起床,打开电脑,一气呵成.第二天如果不看注释,完全不知道自己找到了如此巧妙地 ...