分截排序之二分查找

假如有一个排好序的整型数组,例如「1,2,3,4,5,6,7,8,9」, 从某处截断,后面一段整体移动到左边一段的左边,例如变成「5,6,7,8,9,1,2,3,4」,这样处理后的数组成为分截排序数组,给定一个分截排序数组,如何做二分搜索?

这道题理论上不难,曾经去携程面试的时候问到过,当时没怎么刷算法,答得有点慢,现在手头有几个offer了,索性总结一下:

思路如下,第一步还是找到中位,例如「5,6,7,8,9,1,2,3,4」的中位在9这个数字这里,这时,可能有两种情况,必属其一:第一,中位数处在“左段”,第二,中位数处在“右段”,所谓左段就是整体被从原始有序数组移到左边去的那一段,其余部分统称“右段”,那么如果中位数属于左段,则从开始位置到中位数都是完全排序好的,而从中位数到末尾位置又是一个子分截排序数组。理解清了这一点,就可以写递归了,废话不多说,上代码:

import java.util.ArrayList;
import java.util.BitSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Solution {
	public int findIndex(int[] sectionOrder, int val){
		return innerFindIndex(sectionOrder, 0, sectionOrder.length-1, val);
	}
	
	public int innerFindIndex(int[] arr, int start, int end, int val){
		if(start>end){
			return -1;
		}else if(start==end){
			if(val==arr[start]){
				return start;
			}else{
				return -1;
			}
		}else{
			int mid = (start+end)/2;
			if(arr[mid]==val){
				return mid;
			}
			if(arr[mid]>=arr[start]){
				//mid in left section
				if(val>=arr[start] && val<=arr[mid]){
					//val in leftSection
					return binarySearch(arr, start, mid, val);
				}else{
					return innerFindIndex(arr, mid, end, val);
				}
			}else if(arr[mid]<=arr[end]){
				//mid in right section
				if(val>=arr[mid] && val<=arr[end]){
					return binarySearch(arr, mid, end, val);
				}else{
					return innerFindIndex(arr, start, mid, val);
				}
			}else{
				return -1;
			}
		}
	}
	
	public int binarySearch(int[] arr, int start, int end, int val){
		if(start>end){
			return -1;
		}else if(start==end){
			if(val==arr[start]){
				return start;
			}else{
				return -1;
			}
		}
		int mid = (start+end)/2;
		if(arr[mid]==val){
			return mid;
		}else if(val>arr[mid]){
			return binarySearch(arr, mid+1, end, val);
		}else{
			return binarySearch(arr, start, mid-1, val);
		}
	}
	
    public static void main(String[] args){
    	Solution sol = new Solution();
    	int[] bin = {1,3,5,7,9,13,17};
    	int[] arr={15,16,19,1,3,5,6,7,13};
    	System.out.println(sol.findIndex(arr, 3));
    }
}
点赞