一道折半算法变种的面试题

来源:互联网 发布:想开个淘宝店怎么开 编辑:程序博客网 时间:2024/06/08 11:58

经验之谈:当你看到排好序、查找、logN等字眼时,请第一时间想到折半。

一个排好序的整型数组,然后把数组中的元素循环左移若干位置。

编程实现一种在新的数组中查找某个指定值的算法。要求时间复杂度为O(logN)。

比如原数组是[1,4,9,10,15,16]

循环左移2个位置得到[9,10,15,16,1,4]

元素:15

偏移量:2

位置:4->2


基本思路:变相考查折半查找,先通过折半查找找出元素在原数组中的位置,然后通过与偏移量的计算得到新位置即可。


直接看核心算法,做一下边界判断,优化效率,然后进行折半:

<span style="font-size:18px;"> public static int BinarySearch(int array[], int x) { //排序数组,边界判断,优化 if(x < array[0] || x > array[array.length-1]){ return -1; }  //折半 int mid, left, right; left = 0; right = array.length; mid = (left + right) / 2; while (left <= right) { if(x == array[mid]){ return mid; } else if(x > array[mid]) { left = mid + 1; System.out.println("left:" + left); } else if (x < array[mid]) { right = mid - 1; System.out.println("right:" + right); }     mid=(left+right)/2;     System.out.println("mid:" + mid); } return -1;}</span>


然后跑一下代码:

<span style="font-size:18px;">public static void main(String[] args) {  int array[] = {1,4,9,10,15,16};  System.out.println("数组:");  for (int i = 0; i < array.length; i++) {   System.out.print(array[i] + ",");  }  System.out.println();    Scanner sc = new Scanner(System.in);  System.out.println("请输入你要查找的数字:");  int target = sc.nextInt();  System.out.println("请输入数组循环的偏移量:");  int offset = sc.nextInt();  int index = BinarySearch(array, target);  if(index == -1){  System.out.println("数组中无此元素。");  }else{  System.out.println(target + "在原数组中的下标是  " + index);  System.out.println(target + "在新数组中的下标是  " + (index-offset+array.length)%array.length);  }}</span>

完整源代码如下:

<span style="font-size:18px;">import java.util.Scanner;public class BinarySearch {/** * 权兴权意-2016.10.8 * 一个排好序的整型数组,然后把数组中的元素循环左移若干位置。 * 编程实现一种在新的数组中查找某个指定值的算法。要求时间复杂度为O(logN)。 * 比如原数组是[1,4,9,10,15,16] * 循环左移2个位置得到[9,10,15,16,1,4] * 元素:15 * 偏移量:2 * 位置:4->2 */public static void main(String[] args) {  int array[] = {1,4,9,10,15,16};  System.out.println("数组:");  for (int i = 0; i < array.length; i++) {   System.out.print(array[i] + ",");  }  System.out.println();    Scanner sc = new Scanner(System.in);  System.out.println("请输入你要查找的数字:");  int target = sc.nextInt();  System.out.println("请输入数组循环的偏移量:");  int offset = sc.nextInt();  int index = BinarySearch(array, target);  if(index == -1){  System.out.println("数组中无此元素。");  }else{  System.out.println(target + "在原数组中的下标是  " + index);  System.out.println(target + "在新数组中的下标是  " + (index-offset+array.length)%array.length);  }} public static int BinarySearch(int array[], int x) { //排序数组,边界判断,优化 if(x < array[0] || x > array[array.length-1]){ return -1; }  //折半 int mid, left, right; left = 0; right = array.length; mid = (left + right) / 2; while (left <= right) { if(x == array[mid]){ return mid; } else if(x > array[mid]) { left = mid + 1; System.out.println("left:" + left); } else if (x < array[mid]) { right = mid - 1; System.out.println("right:" + right); }     mid=(left+right)/2;     System.out.println("mid:" + mid); } return -1;}  }</span>

测试结果:

数组:
1,4,9,10,15,16,
请输入你要查找的数字:
100
请输入数组循环的偏移量:
2
数组中无此元素。

 

数组:
1,4,9,10,15,16,
请输入你要查找的数字:
15
请输入数组循环的偏移量:
2
left:4
mid:5
right:4
mid:4
15在原数组中的下标是 4
15在新数组中的下标是 2


1 0