剑指 Offer II 070. 排序数组中只出现一次的数字(540. 有序数组中的单一元素)
题目:
思路:
【0】首先常规的做法必然是不符合进阶的,毕竟要满足O(log n),那么只能二分了,不过幸好的是,数组是有序的。
【1】全数组的二分查找的方式
【2】偶数下标的二分查找的方式
代码展示:
偶数下标的二分查找的方式:
//时间0 ms击败100% //内存41.8 MB击败22.25% //时间复杂度:O(logn),其中 n 是数组 nums 的长度。 //需要在偶数下标范围内二分查找,二分查找的时间复杂度是 O(logn)。 //空间复杂度:O(1)。 class Solution { public int singleNonDuplicate(int[] nums) { int low = 0, high = nums.length - 1; while (low < high) { int mid = (high - low) / 2 + low; mid -= mid & 1; if (nums[mid] == nums[mid + 1]) { low = mid + 2; } else { high = mid; } } return nums[low]; } }
全数组的二分查找的方式:
//时间0 ms击败100% //内存41.6 MB击败51.97% //时间复杂度:O(logn),其中 nnn 是数组 nums 的长度。 //需要在全数组范围内二分查找,二分查找的时间复杂度是 O(logn)。 //空间复杂度:O(1)。 class Solution { public int singleNonDuplicate(int[] nums) { int low = 0, high = nums.length - 1; while (low < high) { int mid = (high - low) / 2 + low; if (nums[mid] == nums[mid ^ 1]) { low = mid + 1; } else { high = mid; } } return nums[low]; } }
常规的做法一般都是O(N)的方式:
//时间1 ms击败22.66% //内存47.3 MB击败26.81% //这种是利用数组中必定是2(n-1)+1的个数,其中n为不同数值的个数。 //假设单独只有一个的数为x,那么必然存在x的左边的个数是2k个。所以存在下标偶数的0与下标奇数的1的数值是一样的。 //同理,由于X的占位是偶数,所以右边是下标奇数的x+1与存在下标偶数的x+2的数值是一样的。 class Solution { public int singleNonDuplicate(int[] nums) { int res = -1; for (int i = 0; i < nums.length; i += 2){ if (i == nums.length-1 || nums[i] != nums[i + 1]){ res = nums[i]; break; } } return res; } } //时间1 ms击败22.66% //内存47.1 MB击败71.6% //这种是利用两相同数值异或为0的特性 class Solution { public int singleNonDuplicate(int[] nums) { int res = 0; for (int i = 0; i < nums.length; i++){ res ^= nums[i]; } return res; } }