• 行百里者半九十 —— 查找算法(中等)


    剑指 Offer 04. 二维数组中的查找
    剑指 Offer 11. 旋转数组的最小数字
    剑指 Offer 50. 第一个只出现一次的字符

    1、二维数组中的查找

    在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个高效的函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
    示例:

    现有矩阵 matrix 如下:
    [
      [1,   4,  7, 11, 15],
      [2,   5,  8, 12, 19],
      [3,   6,  9, 16, 22],
      [10, 13, 14, 17, 24],
      [18, 21, 23, 26, 30]
    ]

    题解1:暴力破解,依次遍历,不是最优解法
    题解2:将矩阵逆时针旋转45度,如下,类似于二叉搜索树,一右上角作为根节点,开始搜索,

     示例代码:

     1 class Solution {
     2 public:
     3     bool findNumberIn2DArray(vector<vector<int>>& matrix, int target) {
     4         int i = matrix.size() - 1, j = 0;
     5         while(i >= 0 && j < matrix[0].size())
     6         {
     7             if(matrix[i][j] > target) i--;
     8             else if(matrix[i][j] < target) j++;
     9             else return true;
    10         }
    11         return false;
    12     }
    13 };
    

    2、旋转数组的最小数字

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

    示例 1:

    输入:[3,4,5,1,2]
    输出:1
    

    示例 2:

    输入:[2,2,2,0,1]
    输出:0
    
    题解1:暴力破解,直接遍历,[n]>[n+1]时,[n+1]就是最小值;
    题解2:二分法,用右边位置和中间位置的元素比较
     1 #include <iostream>
     2 #include <vector>
     3 
     4 using namespace std;
     5 
     6 class Solution {
     7 public:
     8     int minArray(vector<int> &numbers) {
     9         int size = numbers.size();
    10         if (size == 0) {
    11             return 0;
    12         }
    13 
    14         int left = 0;
    15         int right = size - 1;
    16 
    17         while (left < right) {
    18             int mid = left + (right - left) / 2;
    19             // int mid = left + ((right - left) >> 1);
    20             if (numbers[mid] > numbers[right]) {
    21                 // [3, 4, 5, 1, 2],mid 以及 mid 的左边一定不是最小数字
    22                 // 下一轮搜索区间是 [mid + 1, right]
    23                 left = mid + 1;
    24             } else if (numbers[mid] == numbers[right]) {
    25                 // 只能把 right 排除掉,下一轮搜索区间是 [left, right - 1]
    26                 right--;
    27             } else {
    28                 // 此时 numbers[mid] < numbers[right]
    29                 // mid 的右边一定不是最小数字,mid 有可能是,下一轮搜索区间是 [left, mid]
    30                 right = mid;
    31             }
    32         }
    33         return numbers[left];
    34     }
    35 };
    

    3、第一个只出现一次的字符

    在字符串 s 中找出第一个只出现一次的字符。如果没有,返回一个单空格。 s 只包含小写字母。

    示例 1:
    输入:s = "abaccdeff"
    输出:'b'

    示例 2:
    输入:s = ""
    输出:' '

    题解:很容易想到哈希表,第一次对字符串遍历时,使用哈希表映射统计出每个字符出现的次数,第二次遍历时,只有遍历到一个只出现一次的字符,就返回它,否则就返回空格。

     1 class Solution {
     2 public:
     3     char firstUniqueChar(string s) {
     4         unorder_map<int, int> frequency;
     5         for(char c: s){
     6             ++frequency[ch];
     7         }
     8         for(int i=0; i < s.size(); ++i){
     9             if(frequency[s[i]] == i)
    10                 return s[i];
    11         }
    12         return ' ';
    13     }    
    14 };
  • 相关阅读:
    2.8
    2.7
    2.6
    2.5
    2.4第三篇读后感
    2.2第一篇读后感
    2.1
    字符统计
    6468: Snuke's Coloring
    6463: Tak and Hotels II
  • 原文地址:https://www.cnblogs.com/y4247464/p/15580011.html
Copyright © 2020-2023  润新知