剑指offer打卡第四天
查找算法(简单)
一、剑指 Offer 03. 数组中重复的数字
【题目描述】 找出数组中重复的数字。
在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
【分析】:C++11中对unordered_set描述大体如下:无序集合容器(unordered_set)是一个存储唯一(unique,即无重复)的关联容器(Associative container),容器中的元素无特别的秩序关系,该容器允许基于值的快速元素检索,同时也支持正向迭代。
函数模板
template < class Key,
class Hash = hash<Key>,
class Pred = equal_to<Key>,
class Alloc = allocator<Key>
> class unordered_set;
【C++代码】
代码如下:
class Solution {
public:
int findRepeatNumber(vector<int>& nums) {
unordered_set<int> ss;
for(int i = 0;i < nums.size();i++){
if(ss.count(nums[i])!=0)
return nums[i];
ss.insert(nums[i]);
}
return 0;
}
};
二、剑指 Offer 53 - I. 在排序数组中查找数字 I
【题目描述】 统计一个数字在排序数组中出现的次数。
【分析】 解题思路:
排序数组中的搜索问题,二分解法
排序数组nums中的所有数字target形成一个窗口,记窗口左/右边界索引分别为left和right分别对应窗口左边/右边的首个元素。
本题要求统计数字target出现的次数,可转换为:使用二分法分别找到左边界left和右边界right,易得数字target的数量为right-left-1;
【C++代码】
class Solution {
public:
int search(vector<int>& nums, int target) {
if(nums.empty()) return 0;
int l = 0,r = nums.size()-1;
while(l < r){
int mid = l + r >> 1;
if(nums[mid] >= target)
r = mid;
else
l = mid + 1;
}
if(nums[r]!= target) return 0;
int start = r;
l = 0,r = nums.size()-1;
while(l < r){
int mid = (long long)l + (long long)r + 1>>1;
if(nums[mid] <= target)
l = mid;
else
r = mid - 1;
}
int end = r;
return end - start + 1;
}
};
算法解析:
1、初始化:左边界 i = 0,右边界 j = nums.size()-1;
2、循环二分:当闭区间[i,j]无元素时跳出
- 计算中点位置m = (i+ j)/2下取整
- 若nums[m] < target,则target在闭区间[m+1,j]中,因此执行i = m+1;
- 若nums[m] > target, 则target在闭区间[i,m-1]中,因此执行j = m-1;
- 若nums[m] = target, 则右边界right在闭区间[m+1,j]中,左边界left在闭区间[i,m-1]中
三、剑指 Offer 53 - II. 0~n-1中缺失的数字
【题目描述】 一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围0~n-1之内。在范围0~n-1内的n个数字中有且只有一个数字不在该数组中,请找出这个数字。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/que-shi-de-shu-zi-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
【分析】
前n项和的计算公式,求和公式的应用
【C++代码】
代码如下:
class Solution {
public:
int missingNumber(vector<int>& nums) {
int n = nums.size();
int res = (n)*(n+1)/2;
for(auto x :nums) res -= x;
return res;
}
};