0540 Solved

This commit is contained in:
chilim 2020-04-27 16:04:23 +08:00
parent 505dc4120c
commit 6c7e4eb72f
5 changed files with 89 additions and 0 deletions

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 MiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 MiB

View File

@ -0,0 +1,89 @@
题目来源于LeetCode上第540号问题有序数组中的单一元素题目难度为中等目前通过率60.2%
##题目描述
给定一个只包含整数的有序数组每个元素都会出现两次唯有一个数只会出现一次找出这个数
```
示例 1:
输入: [1,1,2,3,3,4,4,8,8]
输出: 2
示例 2:
输入: [3,3,7,7,10,11,11]
输出: 10
注意: 您的方案应该在 O(log n)时间复杂度和 O(1)空间复杂度中运行
```
##题目解析
我们先读题找出题中关键词包含整数的有序数组元素出现两次只有一个数出现一次这里我们可以知道只出现一次的那个元素所在的有序数组元素个数必为奇数这个是解题的关键因为题目要求我们的时间复杂度为O(log n)因此我们可以用二分搜索法
## 解法一二分搜索
首先将lo和hi分别指向数组首尾元素mid指向中间元素这时我们会发现中间元素与其左右两边元素分别有以下三种情况133423433433对于第二种情况我们立马就找到了只出现一次的那个元素那么对于第一种情况mid=mid-1那么以33为界将数组一分为二判断两边的元素个数因为我们知道只出现一次的那个元素所在的有序数组元素个数必为奇数如果33左边的元素个数为奇数那么只出现一次的那个数载左边则将hi移到mid-2位置33的左边如果33右边的元素个数为奇数那么只出现一次的那个数在右边则将lo移到mid+1位置33的右边第三种情况与第二种情况类似分析如果33左边为奇数则hi移到mid-1位置如果33右边为奇数则lo移到mid+2位置以此类推直到lo=hi搜索结束
##动画理解
##代码实现
```
class Solution {
public int singleNonDuplicate(int[] nums) {
int lo = 0;
int hi = nums.length - 1;
while (lo < hi) {
int mid = lo + (hi - lo) / 2;
boolean halvesAreEven = (hi - mid) % 2 == 0;
if (nums[mid + 1] == nums[mid]) {
if (halvesAreEven) {
lo = mid + 2;
} else {
hi = mid - 1;
}
} else if (nums[mid - 1] == nums[mid]) {
if (halvesAreEven) {
hi = mid - 2;
} else {
lo = mid + 1;
}
} else {
return nums[mid];
}
}
return nums[lo];
}
}
```
##复杂度分析
- 时间复杂度O(log n)在每次循环迭代中我们将搜索空间减少了一半
- 空间复杂度O(1)仅用了常数空间
##解法二仅对偶数索引进行二分搜索
我们发现当mid索引为偶数时mid两边的数组元素个数是偶数如果mid索引为奇数时mid两边的数组元素个数为奇数当mid索引为偶数时如果mid=mid+1即解法一的第三种情况因为mid右边个数为偶数所以mid+2到hi个数为奇数那么只出现一次的那个元素肯定在mid的右边将lo移动到mid+2位置如果mid= mid+1那么只出现一次的那个元素肯定在mid的左边或者就是mid如果mid 索引为奇数那么我们为了保证mid索引为偶数将mid移到mid-1位置这样mid索引就变成偶数了重复上述操作直到hi=lo搜索结束
##动画理解
##代码实现
```
class Solution {
public int singleNonDuplicate(int[] nums) {
int lo = 0;
int hi = nums.length - 1;
while (lo < hi) {
int mid = lo + (hi - lo) / 2;
if (mid % 2 == 1) mid--;
if (nums[mid] == nums[mid + 1]) {
lo = mid + 2;
} else {
hi = mid;
}
}
return nums[lo];
}
}
```
##复杂度分析
- 时间复杂度O(log2 / n)=O(log n)我们仅对元素的一半进行二分搜索
- 空间复杂度O(1)仅用了常数空间