剑指Offer刷题记录_Day5
查找算法(中等)
Q1 二维数组的查找
题目:在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个高效的函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
-
思路一:暴力法 时间复杂度O(nm)空间复杂度O(1)
-
思路二:由于二维数组从左至右,从上至下的性质,我们考虑能否用二分搜索的方法。联想BST(Binary Search Tree),从根节点出发,小于当前结点向右搜索,大于当前结点向左搜索。观察题目所构造的矩阵,从左上开始查找和BST情况相似,因此只要想出查找失败的条件即可。注意数组为空的情况。
class Solution {
public:
bool findNumberIn2DArray(vector<vector<int>>& matrix, int target) {
if (matrix.size() == 0 || matrix[0].size() == 0)
{
return false;
}
int m = matrix[0].size(); //列
int n = matrix.size(); //行
int i = 0,j = m-1,temp;
while(i < n && j>=0)
{
temp = matrix[i][j];
if(temp == target) return true;
else if(temp > target) j--;
else i++;
}
return false;
}
};
Q2 旋转数组的最小值
题目描述:
给你一个可能存在 重复 元素值的数组 numbers ,它原来是一个升序排列的数组,并按上述情形进行了一次旋转。请返回旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一次旋转,该数组的最小值为1。
思路一:遍历,知道第一个小于前一个值的值or没有则选择第一个
class Solution {
public:
int minArray(vector<int>& numbers) {
int n = numbers.size();
for(int i = 1;i < n ;i++)
{
if(numbers[i]<numbers[i-1]) return numbers[i];
}
return numbers[0];
}
};
思路二:二分,寻找旋转点
class Solution {
public:
int minArray(vector<int>& numbers) {
int i=0,j=numbers.size()-1,mid;
while(i<j)
{
mid = (i+j)/2;
if(numbers[mid] == numbers[j]) j--;
else if(numbers[mid] < numbers[j]) j = mid;
else i = mid + 1 ;
}
return numbers[i];
}
};
Q3 第一个只出现一次的字符
思路:主要考察对数据结构的理解,可以构造哈希表<元素值,true if 出现次数为1 else false>,然后再遍历一遍字符串数组输出第一个只出现一次的字符
class Solution {
public:
char firstUniqChar(string s) {
unordered_map <char, bool> hash;
for(char c : s)
hash[c] = (hash.find(c) == hash.end()); //若第一次出现,则返回true
//若存在,说明不止一个返回false
for(char c : s)
if(hash[c]) return c;
return ' ';
}
};
本文探讨了剑指Offer中的两个查找算法问题:二维数组的查找及旋转数组的最小值。通过对不同解决策略的分析,如暴力法、二分搜索及哈希表的应用,为读者提供了高效解决问题的思路。

258

被折叠的 条评论
为什么被折叠?



