剑指offer--Day4

本文介绍了三道编程题的解决方案,包括旋转数组找最小值的双指针法,矩阵中单词路径的遍历搜索,以及机器人运动范围的深度优先搜索。强调了理解题目和掌握算法的重要性,提供了详细的代码实现,并提及了深度优先搜索在问题解决中的应用。
摘要由CSDN通过智能技术生成

一位比我大两届的大哥(坐我的对面的侧边)看着我说:没事学习一下,顺便搞个项目出来。我真的会笑,问他怎么知道我没事干,他说没集中精神,我在看着算法题目,在分析,他说我没有集中精神,真厉害,哈哈哈。

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

力扣链接:剑指 Offer 11. 旋转数组的最小数字

其实刚开始写题的时候真的会很懵,会揪着题干不放,但是你从他给的例子去分析又是另一种想法了,多做你才能领会到其中的奥秘,其实最主要的还是要把题给解出来,而不是题目花里胡哨说了一堆,你要揪着哪一方面去实现。

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

给你一个可能存在 重复 元素值的数组 numbers ,它原来是一个升序排列的数组,并按上述情形进行了一次旋转。请返回旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一次旋转,该数组的最小值为 1。

注意,数组 [a[0], a[1], a[2], …, a[n-1]] 旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], …, a[n-2]] 。

题解:双指针解法,数组升序排列,由列子:numbers = [3,4,5,1,2]可以看出,是由中间值往后往前的两个升序有序数组,前边的的数组与后边的数组升序排列,使用双指针的写法,一开始循环就判断左指针如果小于右指针直接返回(这是关键,最小值总是最左边的数),其他都是指针移动,若中间值大于最右边的值,l=mid+1(最小值在右边),若中间值小于最右边的值,r=mid(最小值再右边),相等的时候向右移动一位

一开始:numbers[l]<numbers[r],第一个数组的最小值,小于第二个数组最大值(不存在此类情况)
循环开始:取中间值,

class Solution {
    public int minArray(int[] numbers) {
        int l=0;
        int r=numbers.length-1;
        while(l<r){
            if(numbers[l]<numbers[r]){
                return numbers[l];
            }
            int middle = (l+r)/2;
            
            if(numbers[l]>numbers[middle]){//第一个数组只有一个值的时候
                r=middle;
            }else if(numbers[l]<numbers[middle]){//移动到第二个数组
                l=middle+1;
            }else{ //相等的时候直接移动
                l++;
            }
        }
        return numbers[l];
    }
}

Day4:剑指 Offer 12. 矩阵中的路径

力扣链接:剑指 Offer 12. 矩阵中的路径

题目:给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
在这里插入图片描述
题解:遍历的方式,找到第一个字母所在的位置,从此位置开始向四周开始检索,回溯遍历,每次遍历之后都需要记录一下(用一个特殊字符记录一下),如果为FALSE则重新遍历,再次寻找第一个字母,返回true,则继续查找,直到找到完整的顺序的单词结束。

class Solution {
    int n;
    int m;
    int len;
    public boolean exist(char[][] board, String word) {
        n = board.length;
        m= board[0].length;
        len = word.length();
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                //判断第一个字母位置,从第一个字母位置开始进行搜索
                if(cheakWordAt(board,i,j,word,0)){
                    return true;
                }
            }
        }
        return false;
    }
    boolean cheakWordAt(char[][] board,int i ,int j,String word ,int k ){
        //判断字母是否相同
        if(i<0 || i>=n || j<0 || j>=m || board[i][j]!=word.charAt(k)){
            return false;
        }
        if(k==len-1){
            return true;
        }
        //遍历过的做一个标记
        board[i][j] = '\n';
        //搜索四周
        boolean flag = cheakWordAt(board,i,j+1,word,k+1) || cheakWordAt(board,i+1,j,word,k+1)
                        ||cheakWordAt(board,i-1,j,word,k+1) || cheakWordAt(board,i,j-1,word,k+1);
                    
        board[i][j] = word.charAt(k);

        return flag;
    }
}

Day4:面试题13. 机器人的运动范围

力扣链接:面试题13. 机器人的运动范围

这几道题都需要先了解一下,深度优先搜索跟广度优先搜索。

题目:地上有一个m行n列的方格,从坐标 [0,0] 到坐标 [m-1,n-1] 。一个机器人从坐标 [0, 0] 的格子开始移动,它每次可以向左、右、上、下移动一格(不能移动到方格外),也不能进入行坐标和列坐标的数位之和大于k的格子。例如,当k为18时,机器人能够进入方格 [35, 37] ,因为3+5+3+7=18。但它不能进入方格 [35, 38],因为3+5+3+8=19。请问该机器人能够到达多少个格子?

题解:使用深度优先搜索(Depth First Search,DFS)方法进行求解。根据官方的解释可以看到,随着k的增大,只是从上往下扩大了机器人可以走的范围,所以我们只需要从坐标(0,0)开始往下遍历累计,同时需要计算k与坐标的关系,遇到非法位置的不累计,直到遍历到坐标(m,n)。当碰到边界或者是障碍格子的时候结束此次遍历,直接return达到结束遍历的效果。
在这里插入图片描述

class Solution {
    int m;
    int n;
    int k;
    boolean[][] visited;

    public int movingCount(int m, int n, int k) {
        this.m = m;
        this.n = n;
        this.k = k;
        visited = new boolean[m][n];

        return dfs(0, 0);
    }

    int dfs(int i, int j) {
        if (i < 0 || j < 0 ||i>=m||j>=n|| visited[i][j] || k < Cumulative(i) + Cumulative(j)) {
            return 0;
        }
        visited[i][j] = true;
        return 1 + dfs(i, j + 1) + dfs(i + 1, j);
    }

    int Cumulative(int x) {
        int res = 0;
        while(x!=0){
            res = res+x%10;
            x=x/10;
        }
        return res;
    }
}

end》》》
当你懂得拒绝“廉价”的优越感的时候,你就已经进步了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Recently 祝祝

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值