给定一个数组A及其大小n,同时给定需要查找的元素x,已知数组A是由一个排过序的数组向左移位了一定长度得到的,请返回x在现数组的位置(位置从0开始,(保证数组中元素互异)
输入: {19,30,44,1,2,3,4,5,8,16},10,5
表示输入10个数据,查找数据为5的元素位置。
答案:7
这道题不知道leetCode上有木有,记录一下。
我的想法就是用递归实现二分查找。
先定义每次递归的Left(最左下标元素)、Mid((Left+Right)/2)、Right(最右下标元素),
这种情况下,单纯的二分查找是不行的,要分三种情况:
(1)Left到Mid有序,Mid到Right不完全有序
(2)Left到Mid不完全有序,Mid到Right有序
(3)Left到Mid有序,Mid到Right有序
同时还要想到普通二分查找中需要对Mid、Left、Right进行分析比较:
在(1)情况下,如果元素x介于Left到Mid中间,就递归调用Left到Mid,
如果元素x不介于Left到Mid中间,就递归调用Mid到Right
在(2)情况下,如果元素x介于Mid到Right中间,就递归调用Mid到Right,
如果元素x不介于Mid到Right中间,就递归调用Left到Mid
在(3)情况下,如果元素x介于Left到Mid中间,就递归调用Left到Mid
如果元素x介于Mid到Right中间,就递归调用Mid到Right
我从LeetCode上看到过一种(Left+Right)/2的写法,为了避免Left+Right可能存在溢出的情况:
int mid=left+(right-left)/2; //而不是 int mid=(right+left)/2;
最终代码
{ //给定一个数组A及其大小n,同时给定需要查找的元素x,已知数组A是由一个排过序的 //数组向左移位了一定长度得到的,请返回x在现数组的位置(位置从0开始), //保证数组中元素互异 public int findElement(int[] A, int n, int x) { return div(A, n, x, 0, n - 1); } public int div(int[] A, int n, int x, int left, int right) { if (left > right) return -1; int mid = left + (right - left) / 2; if (A[mid] == x) return mid; if (A[mid] >= A[right] && A[left] <= A[mid])//情况1 Left到Mid有序,Mid到Right不完全有序 { if (x < A[mid] && x >= A[left]) return div(A, n, x, left, mid - 1); else return div(A, n, x, mid + 1, right); } else if (A[mid] <= A[right] && A[left] >= A[mid])//情况2 Left到Mid不完全有序,Mid到Right有序 { if (x > A[mid] && x <= A[right]) return div(A, n, x, mid + 1, right); else return div(A, n, x, left, mid - 1); } else if (A[mid] <= A[right] && A[left] <= A[mid])//情况3 Left到Mid有序,Mid到Right有序 { if (x > A[mid]) return div(A, n, x, mid + 1, right); else return div(A, n, x, left, mid - 1); } return -1; } public static void main(String[] args) { int[] A = {19, 30, 44, 1, 2, 3, 4, 5, 8, 16}; System.out.println(new Finder3().findElement(A, 10, 5)); } }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)