活跃农民
- 积分
- 549
- 大米
- 颗
- 鳄梨
- 个
- 水井
- 尺
- 蓝莓
- 颗
- 萝卜
- 根
- 小米
- 粒
- 学分
- 个
- 注册时间
- 2013-5-12
- 最后登录
- 1970-1-1
|
试了下用binary search解第二问,复杂度在极端情况下从二分退化成了线性,但在随机化test case情况下复杂度还是好于O(N)(也可能是测试设计不够完善)
代码如下,欢迎补充test case
- import java.util.Arrays;
- import java.util.Random;
- /**
- * find magic number
- * (1) find a magic number that A[i] = i in a sorted array (monotonic increasing order), return the smallest magic number (index). return -1 if not found.
- * example: -2 -1 2 4
- * answer: 2 (a[2] == 2)
- *
- * (2) (modified version of problem (1)) elements can be duplicate
- * example: [1, 1, 1]
- * answer: 1 (a[1] == 1)
- */
- public class FindMagicNumber {
- public static void main(String[] args) {
- int[] test1 = new int[] {-2, -1, 3, 4};
- findMagicNumber1(test1);
- findMagicNumber2(test1);
- int[] test2 = new int[] {};
- findMagicNumber1(test2);
- findMagicNumber2(test2);
- int[] test3 = new int[] {0, 1, 2, 3, 4};
- findMagicNumber1(test3);
- findMagicNumber2(test3);
- int[] test4 = new int[] {1, 1, 1};
- findMagicNumber2(test4);
- int[] test5 = new int[] {0, 1, 1, 2, 3};
- findMagicNumber2(test5);
- int[] test6 = new int[] {-1, -1, -1, 3, 4};
- findMagicNumber2(test6);
- int[] test7 = new int[] {-1, -1, -1, 100, 100};
- findMagicNumber2(test7);
- int[] test8 = new int[10000];
- for (int i = 0; i < test8.length; i++) {
- test8[i] = i + 1;
- }
- findMagicNumber2(test8);
- int[] test9 = new int[10000];
- for (int i = 0; i < test9.length; i++) {
- test9[i] = i;
- }
- findMagicNumber1(test9);
- findMagicNumber2(test9);
- int[] test10 = new int[10000];
- for (int i = 0; i < test10.length; i++) {
- if (i > 4998) {
- test10[i] = i + 1;
- } else {
- test10[i] = i;
- }
- }
- findMagicNumber2(test10);
- int[] test11 = new int[10000];
- for (int i = 0; i < test11.length; i++) {
- if (i < 4999) {
- test11[i] = i + 1;
- } else {
- test11[i] = i;
- }
- }
- findMagicNumber2(test11);
- Random rand = new Random();
- int[] test12 = new int[10000];
- int sum = 0;
- int found = 0;
- int tn = 10000;
- for (int k = 1; k <= tn; k++) {
- for (int i = 0; i < test12.length; i++) {
- test12[i] = rand.nextInt(10000) - rand.nextInt(rand.nextInt(300) + 1);
- }
- Arrays.sort(test12);
- found += findMagicNumber2(test12, false) != -1 ? 1 : 0;
- sum += count2;
- }
- System.out.println("Average recursion count is: " + (sum / tn) + ", found " + found + " cases");
- }
- static int count1 = 0;
- static int count2 = 0;
- public static int findMagicNumber1(int[] nums) {
- count1 = 0;
- if (nums.length == 0) {
- System.out.println("Find Magic Number 1");
- System.out.println("Test case is: " + Arrays.toString(nums));
- System.out.println("O(N) = " + nums.length + ", Recursion count = " + count1);
- System.out.println("Result is: -1");
- System.out.println();
- return -1;
- }
- int l = 0;
- int r = nums.length - 1;
- while (l < r) {
- count1++;
- int m = (l + r) >> 1;
- if (nums[m] == m) {
- r = m;
- } else if (nums[m] < m) {
- l = m + 1;
- } else {
- r = m - 1;
- }
- }
- System.out.println("Find Magic Number 1");
- System.out.println("Test case is: " + Arrays.toString(nums));
- System.out.println("O(N) = " + nums.length + ", Recursion count = " + count1);
- System.out.println("Result is: " + (nums[l] == l ? l : -1));
- System.out.println();
- return nums[l] == l ? l : -1;
- }
- public static int findMagicNumber2(int[] nums, boolean print) {
- count2 = 0;
- int res = findMagicNumber2Impl(nums, 0, nums.length - 1);
- if (print) {
- System.out.println("Find Magic Number 2");
- System.out.println("Test case is: " + Arrays.toString(nums));
- System.out.println("O(N) = " + nums.length + ", Recursion count = " + count2);
- System.out.println("Result is: " + (res < nums.length ? res : -1));
- System.out.println();
- }
- return res < nums.length ? res : -1;
- }
- public static int findMagicNumber2(int[] nums) {
- return findMagicNumber2(nums, true);
- }
- private static int findMagicNumber2Impl(int[] nums, int l, int r) {
- count2++;
- if (nums.length == 0) {
- return Integer.MAX_VALUE;
- }
- if (l >= r) {
- return l < nums.length ? (nums[l] == l ? l : Integer.MAX_VALUE) : Integer.MAX_VALUE;
- } else {
- int m = (l + r) >> 1;
- if (nums[m] == m) {
- return findMagicNumber2Impl(nums, l, m);
- } else if (nums[m] > m) {
- int r1 = findMagicNumber2Impl(nums, l, m - 1);
- if (r1 < Integer.MAX_VALUE) {
- return r1;
- } else {
- return findMagicNumber2Impl(nums, nums[m], r);
- }
- } else {
- int r1 = findMagicNumber2Impl(nums, l, nums[m]);
- if (r1 < Integer.MAX_VALUE) {
- return r1;
- } else {
- return findMagicNumber2Impl(nums, m + 1, r);
- }
- }
- }
- }
- }
复制代码
|
|