java—如何以o(logn)时间复杂性解决这个问题

llycmphe  于 2021-07-06  发布在  Java
关注(0)|答案(1)|浏览(387)

问题陈述:给定一个整数排序数组,从给定数组中找出非重复整数。数组中只有1个非重复整数,其他整数范围为2。
输入:[1,1,2,2,4,5,5]输出:4
输入:[10,10,12,12,15,15,16,18,18]输出:16
有人能帮我解决这个时间复杂度为o(logn)的问题吗?
注:n是数组的长度

brccelvz

brccelvz1#

更新
有人指出,原始代码需要数组的切片,如果这是通过一个副本来完成的,这会增加复杂性 O(n) . 以下是使用指向数组的指针的代码版本:
java 语:

  1. public static int singleton(int[] arr, int lo, int hi) {
  2. if (hi == lo) return arr[hi];
  3. int m = (hi + lo) / 2;
  4. if (m % 2 == 1) {
  5. if (arr[m] == arr[m-1]) return singleton(arr, m+1, hi);
  6. if (arr[m] != arr[m+1]) return arr[m];
  7. return singleton(arr, lo, m-1);
  8. }
  9. else {
  10. if (arr[m] == arr[m+1]) return singleton(arr, m+2, hi);
  11. if (arr[m] != arr[m-1]) return arr[m];
  12. return singleton(arr, lo, m);
  13. }
  14. }
  15. public static void main(String args[])
  16. {
  17. System.out.println(singleton(new int[]{ 1,1,2,2,4,5,5 }, 0, 6));
  18. System.out.println(singleton(new int[]{ 10,10,12,12,15,15,16,18,18 }, 0, 8));
  19. System.out.println(singleton(new int[]{1,2,2,5,5,6,6,7,7}, 0, 8));
  20. System.out.println(singleton(new int[]{1,1,2,5,5,6,6,7,7}, 0, 8));
  21. System.out.println(singleton(new int[]{10,10,12,12,15,15,16,16,18}, 0, 8));
  22. }

Python:

  1. def singleton(arr, lo, hi):
  2. if (hi == lo):
  3. return arr[hi]
  4. m = (hi + lo) // 2
  5. if (m % 2 == 1):
  6. if (arr[m] == arr[m-1]):
  7. return singleton(arr, m+1, hi)
  8. if (arr[m] != arr[m+1]):
  9. return arr[m]
  10. return singleton(arr, lo, m-1);
  11. else:
  12. if (arr[m] == arr[m+1]):
  13. return singleton(arr, m+2, hi)
  14. if (arr[m] != arr[m-1]):
  15. return arr[m]
  16. return singleton(arr, lo, m);

原始答案
因为您知道数组中的所有其他整数正好出现两次,所以可以执行二进制搜索来查找只出现一次的值。您需要查找数组的中点,并确定单例是出现在该数字之前、之后还是该数字。如果是在之前或之后,则继续搜索,但只搜索数组的该部分(最多一半)。这是 O(logn) . 在python中(注意:当我最初回答这个问题时,它没有被标记为 java -我随后在下面添加了一个java解决方案)您可以将其实现为:

  1. def singleton(arr):
  2. m = len(arr) // 2
  3. if (m == 0):
  4. return arr[0]
  5. if m % 2 == 1:
  6. if arr[m] == arr[m-1]:
  7. return singleton(arr[m+1:])
  8. if arr[m] != arr[m+1]:
  9. return arr[m]
  10. return singleton(arr[:m])
  11. else:
  12. if arr[m] == arr[m+1]:
  13. return singleton(arr[m+2:])
  14. if arr[m] != arr[m-1]:
  15. return arr[m]
  16. return singleton(arr[:m+1])

示例用法:

  1. print(singleton([1,1,2,2,4,5,5]))
  2. print(singleton([10,10,12,12,15,15,16,18,18]))
  3. print(singleton([1,2,2,5,5,6,6,7,7]))
  4. print(singleton([1,1,2,5,5,6,6,7,7]))
  5. print(singleton([10,10,12,12,15,15,16,16,18]))

输出:

  1. 4
  2. 16
  3. 1
  4. 2
  5. 18

我不是javaMaven,所以这可能不是最有效的方法,但确实有效:

  1. public static int singleton(int[] arr) {
  2. int m = arr.length / 2;
  3. if (m == 0) return arr[0];
  4. if (m % 2 == 1) {
  5. if (arr[m] == arr[m-1]) return singleton(Arrays.copyOfRange(arr, m+1, arr.length));
  6. if (arr[m] != arr[m+1]) return arr[m];
  7. return singleton(Arrays.copyOfRange(arr, 0, m));
  8. }
  9. else {
  10. if (arr[m] == arr[m+1]) return singleton(Arrays.copyOfRange(arr, m+2, arr.length));
  11. if (arr[m] != arr[m-1]) return arr[m];
  12. return singleton(Arrays.copyOfRange(arr, 0, m+1));
  13. }
  14. }
  15. public static void main(String args[])
  16. {
  17. System.out.println(singleton(new int[]{ 1,1,2,2,4,5,5 }));
  18. System.out.println(singleton(new int[]{ 10,10,12,12,15,15,16,18,18 }));
  19. System.out.println(singleton(new int[]{1,2,2,5,5,6,6,7,7}));
  20. System.out.println(singleton(new int[]{1,1,2,5,5,6,6,7,7}));
  21. System.out.println(singleton(new int[]{10,10,12,12,15,15,16,16,18}));
  22. }
展开查看全部

相关问题