算法题day04

1.矩阵中的路径
请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一格开始,每一步可以在矩阵中向左、右、上、下移动一格。如果一条路径经过了矩阵的某一格,那么该路径不能再次进入该格子。例如,在下面的3×4的矩阵中包含一条字符串“bfce”的路径(路径中的字母用加粗标出)。
[[“a”,“b”,“c”,“e”],
[“s”,“f”,“c”,“s”],
[“a”,“d”,“e”,“e”]]
但矩阵中不包含字符串“abfb”的路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入这个格子。
在这里插入图片描述
解:从二维数组第一个位置开始遍历,每个位置都有四个方向可以进行查找,当有一个方向位置的字符和给定字符串中对应该位置的字符相等时,就将当前位置转移到下一位置重复操作。数组行为i,列为j,四个方向分别对应(i,j-1),(i-1,j),(i,j+1),(i+1,j)左上右下,使用递归循环进行判断是否有和给定字符串相等元素,越界条件为i,j<0,i >= board.length,j >= board[0].length,终止条件为字符串遍历到最后一位,或二维数组遍历结束

class Solution {
    public boolean exist(char[][] board, String word) {
        char[] words = word.toCharArray();
        for(int i = 0;i < board.length;i++){
            for(int j = 0;j < board[0].length;j++){
                if(dfs(board,words,i,j,0)){
                    return true;
                }
            }
        }
        return false;
    }

    public boolean dfs(char[][] board,char[] words,int i,int j,int k){
        if(i >= board.length || i < 0 || j >= board[0].length || j < 0 || board[i][j] != words[k]){
            return false;
        }
        if(k == words.length-1){
            return true;
        }
        board[i][j] = '\0';
        boolean res = dfs(board, words, i + 1, j, k + 1) || dfs(board, words, i - 1, j, k + 1) || 
                      dfs(board, words, i, j + 1, k + 1) || dfs(board, words, i , j - 1, k + 1);
        board[i][j] = words[k];
        return res;
    }
}

2.机器人的运动范围
地上有一个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。请问该机器人能够到达多少个格子?
在这里插入图片描述
解:和上题类似,使用深度优先搜索,不同点在于,这里从第一个元素出发,每次判断右和下即可,如果不满足条件返回后每次只搜索右下两个方向就可完成遍历,还需要另写一个数位之和的方法进行判断数位之和是否满足要求。
时间复杂度 O(MN)O(MN) : 最差情况下,机器人遍历矩阵所有单元格,此时时间复杂度为 O(MN)O(MN) 。
空间复杂度 O(MN)O(MN) : 最差情况下,Set visited 内存储矩阵所有单元格的索引,使用 O(MN)O(MN) 的额外空间。

class Solution {
    public int movingCount(int m, int n, int k) {
        boolean[][] visit = new boolean[m][n];
        return dfs(visit,m,n,k,0,0);
    }
    private int dfs(boolean[][] visit,int m,int n,int k,int i,int j){
        if(i>=m||j>=n||visit[i][j]||getSum(i)+getSum(j)>k){
            return 0;
        }
        visit[i][j] = true;
        return 1 + dfs(visit,m,n,k,i+1,j) + dfs(visit,m,n,k,i,j+1);
    }

    private int getSum(int n){
        int sum = 0;
        while(n > 0){
            sum += n%10;
            n = n/10;
        }
        return sum;
    }
}

**3.剪绳子 一 **
给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m、n都是整数,n>1并且m>1),每段绳子的长度记为 k[0],k[1]…k[m-1] 。请问 k[0]k[1]…*k[m-1] 可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
在这里插入图片描述
解:数学推导法:
要先分析出2个问题,才能方便求解,①切多少段最好②每段多少长度
在这里插入图片描述
将问题转化为求 y = x的1/x次方的最大值,
可以得出结论,①等分为a段乘积最大,a为n/x,x为每段长度
②尽可能将绳子以长度 3 等分为多段时,乘积最大。

在这里插入图片描述
时间复杂度 O(1): 仅有求整、求余、次方运算。
求整和求余运算:资料提到不超过机器数的整数可以看作是 O(1) ;
幂运算:查阅资料,提到浮点取幂为 O(1)。
空间复杂度 O(1): 变量 a 和 b 使用常数大小额外空间。

class Solution {
    public int cuttingRope(int n) {
        if(n <= 3){
            return n-1;
        }
        int a = n / 3;
        int b = n % 3;
        if(b == 0){
            return (int)Math.pow(3,a);
        }else if(b == 1){
            return (int)Math.pow(3,a-1)*4;
        }else{
            return (int)Math.pow(3,a)*2;
        }
    }
}

4.剪绳子 二
给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m、n都是整数,n>1并且m>1),每段绳子的长度记为 k[0],k[1]…k[m - 1] 。请问 k[0]k[1]…*k[m - 1] 可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。
在这里插入图片描述
解:利用循环取余方法

class Solution {
    public int cuttingRope(int n) {
        if(n <= 3) return n - 1;
        long res=1L;
        int p=(int)1e9+7;
        //贪心算法,优先切三,其次切二
        while(n>4){
            res=res*3%p;
            n-=3;
        }
        //出来循环只有三种情况,分别是n=2、3、4
        return (int)(res*n%p);
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值