前言
本博文部分图片, 思路来自于剑指offer 或者编程珠玑
问题描述
思路
书中给出了两种思路
思路一 : 遍历一次列表找出最小的元素
思路二 : 如果 head < tail 则说明arr本身就是一个有序的数列
否则如果 head==tail==(head+tail/2) 这个是不能用下面的方式判定, 所以采用顺序比较,
否则 计算head, tail的中间索引
如果 idx大于head元素 即说明其在第一个递增子序列中, 这时最小的元素在idx后面, 更新head为idx,
否则如果 idx小于tail元素 即说明其在第二个递增子序列中, 这时最小的元素在idx前面, 更新tail为idx
最终head会指向第一个递增子序列的最大元素, tail会执行第二个递增子序列的最小元素, 并且二者相邻[循环判断条件]
参考代码
/**
* file name : Test26FindMinInSubOrderedSeq.java
* created at : 9:28:22 AM Jun 5, 2015
* created by
*/
package com.hx.test04;
public class Test26FindMinInSubOrderedSeq {
// 找出半排序的数组中最小的元素 [序列由一个有序序列左移动得到]
public static void main(String []args) {
int[] arr = {18, 19, 20, 22, 27, 28, 32, 34, 37, 38, 38, 48, 48, 4, 6, 11, 17 };
int minIdx = findMinInSubOrderedSeq01(arr);
Log.log(minIdx);
minIdx = findMinInSubOrderedSeq02(arr);
Log.log(minIdx);
// String str = "4 6 11 17 18 19 20 22 27 28 32 34 37 38 38 48 48";
// Log.log(str.replaceAll(" ", ", ") );
}
// 思路 : 遍历arr数组找到最小元素的索引
public static int findMinInSubOrderedSeq01(int[] arr) {
int min = Integer.MAX_VALUE, idx = -1;
for(int i=0; i<arr.length; i++) {
if(arr[i] < min) {
min = arr[i];
idx = i;
}
}
return idx;
}
// 思路 : 令head, tail分别为arr的第一个元素和最后一个元素索引
// 如果head < tail 则说明arr本身就是一个有序的数列
// 否则如果 head==tail==(head+tail/2) 这个是不能用下面的方式判定, 所以采用顺序比较
// 例如 : {0, 1, 1, 1, 1 } -> {1, 0, 1, 1, 1 }/ {1, 1, 1, 0, 1 } 这两种变形都是无法判断的, head, tail指向的均是1
// 否则 计算head, tail的中间索引
// 如果idx大于head元素 即说明其在第一个递增子序列中, 这时最小的元素在idx后面, 更新head为idx
// 如果idx小于tail元素 即说明其在第二个递增子序列中, 这时最小的元素在idx前面, 更新tail为idx
// 最终head会指向第一个递增子序列的最大元素, tail会执行第二个递增子序列的最小元素, 并且二者相邻[循环判断条件]
public static int findMinInSubOrderedSeq02(int[] arr) {
int head = 0, tail = arr.length - 1;
if(arr[head] < arr[tail]) {
return head;
} else if(arr[head] == arr[tail] && arr[head] == arr[((head + tail) >> 1 )]) {
return findMinInSubOrderedSeq01(arr);
}
// arr[head] > arr[tail]
int idx = -1;
while (head != (tail - 1) ) {
idx = (head + tail) >> 1;
if(arr[idx] > arr[head]) {
head = idx;
} else {
tail = idx;
}
}
return tail;
}
}
效果截图
总结
对于 思路二, 看着是否是很像二分查找呢?, 利用了有序旋转数组的性质, 得出了上面精巧的算法
注 : 因为作者的水平有限,必然可能出现一些bug, 所以请大家指出!