day 4
1.剑指 Offer 03. 数组中重复的数字【简单】
在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
思路:只需要找到任意的一个重复数字即可,直接遍历O(n)
//直接遍历
int findRepeatNumber(vector<int>& nums) {
vector<int> count(nums.size()); //vector开定长,int型赋0
for(auto i=nums.begin();i!=nums.end();i++){ //遍历vector容器
int n=*i;
if((++count[n])==2)
return n;
}
return -1;
}
//hash表
int findRepeatNumber(vector<int>& nums) {
unordered_map<int, bool> t;
for(int n : nums) {
if(t[n])
return n;
t[n] = 1;
}
return -1;
}
\qquad
2.剑指 Offer 53 - I. 在排序数组中查找数字 I【简单】
统计一个数字在排序数组中出现的次数。
思路一:直接遍历数组,O(n)
思路二:二分法找到重复数字的边界low
,high
,个数为high-low+1
//直接遍历
int search(vector<int>& nums, int target) {
int n=0;
for(auto i:nums)
if(i==target)
n++;
return n;
}
//二分法
int search(vector<int>& nums, int target) {
int low = 0;
int high = nums.size() - 1;
while (low <= high) { //二分找到左右边界
int mid = low + (high - low) / 2;
if(nums[mid] < target)
low = mid + 1;
else if (nums[mid] > target)
high = mid - 1;
else { //此时nums[mid] = target,所有重复数字在low到high之间
if (nums[low] == nums[high]) //确定了边界
return high - low + 1;
if (nums[low] < target) //向内逼近
low++;
if (nums[high] > target) //向内逼近
high--;
}
}
return 0;
}
\qquad
3.剑指 Offer 53 - II. 0~n-1中缺失的数字【简单】
一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围0~n-1之内。在范围0~n-1内的n个数字中有且只有一个数字不在该数组中,请找出这个数字。
思路:这个数字处到结尾都是数>下标,这个数字之前都是数=下标。
class Solution {
public:
int missingNumber(vector<int>& nums) {
int left=0,right=nums.size()-1;
while(left<=right){ //二分法
int mid=left+(right-left)/2;
if(nums[mid]>mid)
right=mid-1;
else //此处为nums[mid]==mid
left=mid+1;
}
return left;
/*若判断条件为 left < right,则将上条语句改为以下内容
if(nums[left]==left) //说明后一个为缺失
return left+1;
else //else if(nums[left]>left) <此处为缺失
return left;
*/
}
};