剑指Offer 11 12

44 阅读2分钟

这是我参与8月更文挑战的第5天,活动详情查看:8月更文挑战

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

题目

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组 [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

方法一

朴素方法:遍历一遍数组记录最小值

class Solution {
    public int minArray(int[] numbers) {
        int res = 0x3f3f3f3f;
        for (int x : numbers)
            res = Math.min(x, res);
        return res;
    }
}

时间复杂度: O(n)

空间复杂度: O(1)

方法二

二分:此题得稍微做些调整才能用二分,根据二分的定义,在我们答案的左右两边应该分别满足不同的特性,即在本题中,答案左边的点都要大于等于数组的第一个元素,答案右边的都要小于数组的第一个元素,注意,答案右边的点不能小于等于。 所以,我们首先得把数组最后的元素中和第一个元素相等的元素删除。

class Solution {
    public int minArray(int[] numbers) {
        int n = numbers.length - 1;
        if (n == 0) return numbers[0];
        while(n != 0 && numbers[n] == numbers[0]) n --;
​
        int l = 0, r = n;  
        while(l < r) {
            int mid = l + r >> 1;
            if (numbers[mid] < numbers[0]) r = mid;
            else l = mid + 1;
        }
​
        return numbers[l] > numbers[0] ? numbers[0] : numbers[l];
    }
}

时间复杂度: O(logn)

空间复杂度: O(1)

剑指 Offer 12. 矩阵中的路径

题目

给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。

单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。

例如,在下面的 3×4 的矩阵中包含单词 "ABCCED"(单词中的字母已标出)。

示例 1:

输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"
输出:true

示例 2:

输入:board = [["a","b"],["c","d"]], word = "abcd"
输出:false

提示:

  • 1 <= board.length <= 200
  • 1 <= board[i].length <= 200
  • board 和 word 仅由大小写英文字母组成

方法一

深度优先搜索(回溯):枚举矩阵中的点,从该点开始往下搜:当该点的值和单词中的第index位置的字符一样时,接着往下搜索;否则返回。直到搜到index等于单词长度时,说明矩阵中存在该单词,返回true

class Solution {
    
    int[] dx= {0,0,1,-1}, dy = {1,-1,0,0};
    
    public boolean exist(char[][] board, String word) {
        char[] s = word.toCharArray();
​
        for (int i = 0; i < board.length; i ++ )
            for (int j = 0; j < board[0].length; j ++ )
                if (dfs(board, s, i, j, 0))
                    return true;
        return false;
    }
    
    boolean dfs(char[][] board, char[] word, int x, int y, int index) {
        if (board[x][y] != word[index]) return false;
        if (index == word.length - 1) return true;
        board[x][y] = '.';
        for (int i = 0; i < 4; i ++ ) {
            int a = x + dx[i], b = y + dy[i];
            if (a < 0 || a >= board.length || b < 0 || b >= board[0].length) continue;
            if (board[a][b] != '.') {
                if (dfs(board, word, a, b, index + 1))
                    return true;
            }
        }   
        board[x][y] = word[index];
        return false;
    }
}

时间复杂度: O(nm3^k),最差情况下,需要遍历矩阵中长度为 K 字符串的所有方案,时间复杂度为 O(3^k),有nm个点

空间复杂度: O(K),递归深度最深为字符串长度

注意: 当矩阵中的当前字符和单词的第index个字符相等时,我们把矩阵中的当前字符改为.,防止进入到下一层时,又回到该点。等到该层全部结束时,恢复现场。