剑指offer--查找算法(中等)

剑指offer打卡第五天

  • 查找算法(中等)
    • 一、剑指 Offer 04. 二维数组中的查找
    • 二、剑指 Offer 11. 旋转数组的最小数字
    • 三、剑指 Offer 50. 第一个只出现一次的字符


查找算法(中等)

一、剑指 Offer 04. 二维数组中的查找

【题目描述】
在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个高效的函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
【分析】
(单调性扫描)O(n+m)
核心在于发现每个子矩阵右上角的数学性质:
如图:
剑指offer--查找算法(中等)_第1张图片
因此我们可以从整个矩阵的右上角开始枚举,假设当前枚举的数是x,:

  • 如果x等于target,则说明我们找到了目标值,返回ture;
  • 如果x小于target,则x左边的数一定小于target,可以直接删除当前一行(i++);
  • 如果x大于target,则x下边的数一定大于target,可以直接删除当前一列(j–);
    当我们排除整个矩阵后任然没有找到目标,就返回false;

【C++代码】

class Solution {
public:
    bool findNumberIn2DArray(vector<vector<int>>& matrix, int target) {
        if(matrix.empty()||matrix[0].empty())
            return false;
        int i = 0,j = matrix[0].size()-1;
        while(i < matrix.size()&&j >=0){
            if(matrix[i][j] == target)
                return true;
            if(matrix[i][j] > target)
                j--;
            else i++;
        }
        return false;
    }
};

二、剑指 Offer 11. 旋转数组的最小数字

【题目描述】

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一个旋转,该数组的最小值为1

【分析】
二分O(n)
为了便于分析,我们先将数组中的数画在二维坐标系中,横坐标表示数组小标,纵坐标表示数值,如图所示,图中水平实现段表示相同的元素
剑指offer--查找算法(中等)_第2张图片
从图中发现,除了最后水平的一段(黑色水平那段)之外,其余部分满足二分性质:竖直虚线左边的数满足nums[i] >=nums[0];而竖直虚线右边的数不满足这个条件。
所以我们将水平的一段删除即可。
另外,不要忘记处理数组完全单调的特殊情况:
当我们删除最后水平的一段之后,如果剩下的最后一个数大于等于第一个数,则说明完全单调。
【时间复杂度】
二分的时间复杂度是O(logn),删除最后水平一段的时间复杂度最坏是 O(n)O(n),所以总时间复杂度是 O(n)。

【C++代码】

class Solution {
public:
    int minArray(vector<int>& nums) {
        int n = nums.size()-1;
        if(n < 0) return -1;
        while(n> 0&& nums[n] == nums[0]) n--;
        if(nums[n] >= nums[0]) return nums[0];
        int l = 0,r = n;
        while(l <r){
            int mid = l+r >> 1;
            if(nums[mid] < nums[0])
                r = mid;
            else l = mid + 1;
        }
        return nums[r];
    }
};

三、剑指 Offer 50. 第一个只出现一次的字符

【题目描述】
在字符串 s 中找出第一个只出现一次的字符。如果没有,返回一个单空格。 s 只包含小写字母。
【分析】
本题考查哈希表的使用,本文介绍哈希表和有序哈希表两种解法。其中,在字符串长度较大、重复字符很多时,“有序哈希表”解法理论上效率更高。
法一:哈希表
1、遍历字符串s,使用哈希表统计“各个字符数量是否>1”
2、再遍历字符串s,在哈希表中找到首个"数量为1的字符",并返回。

【C++代码】

class Solution {
public:
    char firstUniqChar(string s) {
        unordered_map<char,int> count;
        for(auto c:s) count[c]++;
        char res = ' ';
        for(auto c  :s)
        if(count[c] == 1){
            res = c;
            break;
        }
        return res;
    }
};

你可能感兴趣的:(剑指offer,算法,数据结构)