剑指offer刷题查找算法
Posted 非晚非晚
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指offer刷题查找算法相关的知识,希望对你有一定的参考价值。
记录在Leetcode刷《剑指offer》的笔记,希望提高自己的算法基础和编程水平。这一篇文章刷的是查找算法的题目集合,在CSDN做一下记录,随时更新,一起学习吧。
如果顺序查找耗时间比较多,则重点考虑使用二分查找或者哈希查找算法。
刷题链接:https://leetcode-cn.com/leetbook/read/illustration-of-algorithm/59bx1r/
1. 剑指 Offer 03. 数组中重复的数字
-
题目
-
提交答案
思路:利用计数排序的思路,先遍历一遍,找出序列中的最大值,然后创建一个数组。每个数组元素存放的是对应位置的数据个数。
class Solution {
public:
int findRepeatNumber(vector<int>& nums) {
int myMax = 0;
for(int i = 0; i < nums.size(); i++)
{
myMax = max(myMax, nums[i]);
}
vector<int> myVec(myMax + 1, 0);
for(int i = 0; i < nums.size();i++)
{
if(myVec[nums[i]] == 0) myVec[nums[i]]++;
else return nums[i];
}
return -1;
}
};
- 题目解析
思路:哈希解法。必须要掌握的一种方法。
class Solution {
public:
int findRepeatNumber(vector<int>& nums) {
unordered_map<int, bool> map;
for(int num : nums) {
if(map[num]) return num;//已经有一个数据了
map[num] = true;
}
return -1;
}
};
2. 剑指 Offer 04. 二维数组中的查找
- 题目
- 提交答案
思路:两层循环,遇到大于target的值就跳至下一行。
class Solution {
public:
bool findNumberIn2DArray(vector<vector<int>>& matrix, int target) {
for (int i = 0; i < matrix.size(); i++) {
for (int j=0; j < matrix[0].size(); j++) {
if (matrix[i][j] == target) return true;
if (matrix[i][j] > target)
{
break;
}
}
}
return false;
}
};
- 题目解析
思路:从左下角开始遍历。
当 matrix[i][j] > target 时,执行 i-- ,即消去第 i 行元素;
当 matrix[i][j] < target 时,执行 j++ ,即消去第 j 列元素;
当 matrix[i][j] = target 时,返回 true,代表找到目标值。
class Solution {
public:
bool findNumberIn2DArray(vector<vector<int>>& matrix, int target) {
int i = matrix.size() - 1, j = 0;
while(i >= 0 && j < matrix[0].size())
{
if(matrix[i][j] > target) i--;
else if(matrix[i][j] < target) j++;
else return true;
}
return false;
}
};
3. 剑指 Offer 11. 旋转数组的最小数字
-
题目
-
提交答案
思路:倒序查找,直到找到比当前值大的数字。
class Solution {
public:
int minArray(vector<int>& numbers) {
for(int i = numbers.size() - 1; i >= 0; i--)
{
int j = i - 1;
if( j < 0) break;
if(numbers[j] > numbers[i]) return numbers[i];
}
return numbers[0];
}
};
- 题目解析
思路:二分查找
class Solution {
public:
int minArray(vector<int>& numbers) {
int i = 0, j = numbers.size() - 1;
while (i < j) {
int m = (i + j) / 2;
if (numbers[m] > numbers[j]) i = m + 1;
else if (numbers[m] < numbers[j]) j = m;
else j--;
}
return numbers[i];
}
};
4. 剑指 Offer 50. 第一个只出现一次的字符
- 题目
- 提交答案
思路:这里考察哈希表,不过哈希表的值需要设定一个结构体类型,分别存储字符出现的顺序和次数。
struct Mystruct
{
int arr;//次序
int count;//计数
};
class Solution {
public:
char firstUniqChar(string s) {
if(s.size() == 0) return ' ';
int arr = 0;//次序
map<char, Mystruct> myMap;
for(int i = 0; i < s.size(); i++)
{
myMap[s[i]].count++;
if(myMap[s[i]].count == 1)//首次出现
{
myMap[s[i]].arr = arr;
arr++;//下次
}
}
arr = 100;
char tmp = ' ';
for(auto x : myMap)
{
if(x.second.count == 1 && arr > x.second.arr)
{
arr = x.second.arr;
tmp = x.first;
}
}
return tmp;
}
};
- 题目解析
思路:题目解析中运用了vector配合unordered_map进行实现。
class Solution {
public:
char firstUniqChar(string s) {
vector<char> keys;
unordered_map<char, bool> dic;
for(char c : s) {
if(dic.find(c) == dic.end())
keys.push_back(c);
dic[c] = dic.find(c) == dic.end();
}
for(char c : keys) {
if(dic[c]) return c;
}
return ' ';
}
};
5. 剑指 Offer 53 - I. 在排序数组中查找数字
- 题目
- 提交答案
思路:考察二分查找。
class Solution {
public:
int search(vector<int>& nums, int target) {
if(nums.size() == 0)return 0;
int L = 0;
int H = nums.size() - 1;
int mid = (L + H)/2;
//二分查找
while(L <=H)
{
if(target == nums[mid])break;
else if(target > nums[mid]) {L = mid +1;}
else H = mid - 1;
mid = (L + H)/2;
}
if(nums[mid] != target) return 0;
int count = 0;
int i = 0;
cout<<nums[mid];
while(mid + i < nums.size())//找右边
{
if( nums[mid + i] == target)
{
count++;
i++;
}
else break;
}
i = 1;
while(mid - i >= 0)//找左边
{
if( nums[mid - i] == target)
{
count++;
i++;
}
else break;
}
return count;
}
};
- 题目解析
思路:也是二分查找,只不过变形了一下,如果相等的时候不退出来,等到搜索到边界的时候才退。
class Solution {
public:
int search(vector<int>& nums, int target) {
// 搜索右边界 right
int i = 0, j = nums.size() - 1;
while(i <= j) {
int m = (i + j) / 2;
if(nums[m] <= target) i = m + 1;
else j = m - 1;
}
int right = i;
// 若数组中无 target ,则提前返回
if(j >= 0 && nums[j] != target) return 0;
// 搜索左边界 right
i = 0; j = nums.size() - 1;
while(i <= j) {
int m = (i + j) / 2;
if(nums[m] < target) i = m + 1;
else j = m - 1;
}
int left = j;
return right - left - 1;
}
};
6. 剑指 Offer 53 - II. 0~n-1 中缺失的数字
- 题目
- 题目解析
思路:二分查找
class Solution {
public:
int missingNumber(vector<int>& nums) {
int i = 0, j = nums.size() - 1;
while(i <= j) {
int m = (i + j) / 2;
if(nums[m] == m) i = m + 1;
else j = m - 1;
}
return i;
}
};
以上是关于剑指offer刷题查找算法的主要内容,如果未能解决你的问题,请参考以下文章
剑指 Offer(第 2 版)刷题 | 04. 二维数组中的查找