【剑指 Offer】第 5 天

90 阅读2分钟

Offer 驾到,掘友接招!我正在参与2022春招系列活动-刷题打卡任务,点击查看活动详情

一、前言

刷题啊!!!

开始刷 “剑指 Offer” 31天。刷完时间:2022.3.6 ~ 2022.3.20。



二、题目

(1)剑指 Offer 04. 二维数组中的查找

题目描述


在一个 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]
]
给定 target = 5,返回 true。

给定 target = 20,返回 false。

限制:

  • 0 <= n <= 1000
  • 0 <= m <= 1000

题解


观察规律:从左到右,从上到下,数值越来越大。

利用 二分查找法 思路:

  • 目标值 < 当前值:行数 + 1
  • 目标值 > 当前值:列数 - 1
  • 目标值 = 当前值:找到啦。

初始位置:右上角 [0][columns - 1]

边界条件:坐标超出数组边界。

AC 代码如下:

class Solution {
    public boolean findNumberIn2DArray(int[][] matrix, int target) {
        if (matrix == null || matrix.length == 0 ||
        matrix[0] == null || matrix[0].length == 0)
            return false;

        int columns = matrix[0].length; // 列数
        int rows = matrix.length;       // 行数

        int x = 0, y = columns - 1;

        while (x < rows && y >= 0) {

            if (target == matrix[x][y]) return true;

            if (target < matrix[x][y]) {

                --y;
            } else if (target > matrix[x][y]) {

                ++x;
            }
        }
        return false;
    }
}

(2)剑指 Offer 11. 旋转数组的最小数字

题目描述


把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。

给你一个可能存在 重复 元素值的数组 numbers ,它原来是一个升序排列的数组,并按上述情形进行了一次旋转。请返回旋转数组的最小元素。例如,数组 [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

题解


这种题最容易想到是:暴力法,直接遍历一次。

AC 代码如下:

class Solution {
    public int minArray(int[] numbers) {
        int low = 0;
        int high = numbers.length - 1;
        while (low < high) {
            int pivot = low + (high - low) / 2;
            if (numbers[pivot] < numbers[high]) {
                high = pivot;
            } else if (numbers[pivot] > numbers[high]) {
                low = pivot + 1;
            } else {
                high -= 1;
            }
        }
        return numbers[low];
    }
}

(1)面试题50. 第一个只出现一次的字符

题目描述


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

示例 1:

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

输入:s = "" 
输出:' '

限制:0 <= s 的长度 <= 50000

题解


题目理解,利用 HashMap

  1. HashMap 筛选出只出现过一次的字母
  2. HashSet 保存只出现过一次的字母
  3. 再遍历一次,找到第一个只出现过一次的字母

AC 代码如下:

class Solution {
    public char firstUniqChar(String s) {
        if (null == s || s == "" ) return ' ';
        Map<Character, Integer> map = new HashMap<>();
        for (int i = 0; i < s.length(); ++i) {
             char c = s.charAt(i);
             if (map.containsKey(c)) {
                 map.put(c, 2);
                 continue;
             }
             map.put(c, 1);
        }
        Set<Character> set = new HashSet<>();
        for (Map.Entry<Character, Integer> entry : map.entrySet()) {
            if (entry.getValue() == 1) set.add(entry.getKey());
        }
        if (set.isEmpty()) return ' ';
         for (int i = 0; i < s.length(); ++i) {
             char c = s.charAt(i);
             if (set.contains(c)) {
                 return c;
             }
        }
        return ' ';
    }
}