剑指offer

Posted lgh544

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指offer相关的知识,希望对你有一定的参考价值。

1、剪绳子

给你一根长度为n的绳子,请把绳子剪成整数长的m段(m、n都是整数,n>1并且m>1,m<=n),每段绳子的长度记为k[1],...,k[m]。请问k[1]x...xk[m]可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。

输入描述:

输入一个数n,意义见题面。(2 <= n <= 60)

输出描述:

输出答案。
示例1

输入

8

输出

18
/**
    * 解题思路,找出最优解的规律
    * 当target等于1,2,3的时候,结果是固定的
    * 当target大于3的时候,可以看以下数据
    * target=4, 最优解:2 2
    * target=5, 最优解:3 2
    * target=6, 最优解:3 3
    * target=7, 最优解:3 2 2
    * target=8, 最优解:3 3 2
    * target=9, 最优解:3 3 3
    * target=10,最优解:3 3 2 2
    * target=11,最优解:3 3 3 2
    * target=12,最优解:3 3 3 3
    * target=13,最优解:3 3 3 2 2
    * target=14,最优解:3 3 3 3 2
    * target=15,最优解:3 3 3 3 3
    *
    * 所以不难发现3和2的个数规律
    */

//动态规划
public class Solution {
    
    public int cutRope(int target) {
        int[] dp=new int[target+1];
        if(target<=3)return target-1;
/*
        下面3行是n>=4的情况,跟n<=3不同,4可以分很多段,比如分成1、3,
        这里的3可以不需要再分了,因为3分段最大才2,不分就是3。记录最大的。
        第二个循环为什么j<=i/2是因为1*3和3*1是一样的,没必要计算在内,只要计算到1*3和2*2就好了
         */
        dp[1]=1;
        dp[2]=2;
        dp[3]=3;
        for(int i=4;i<=target;i++){
            for(int j=1;j<=i/2;j++){
                dp[i]=Math.max(dp[i],dp[j]*dp[i-j]);
            }
        }
        return dp[target];
    
        //找规律
        /*if(target<=3)return target-1;
        int a=target/3;
        int b=target%3;
       if(b==2)
           return (int)Math.pow(3,a)*2;
        if(b==1)
             return (int)Math.pow(3,a-1)*4;
        if(b==0)
             return (int)Math.pow(3,a);
        return 0;*/
    }
}

 

2、机器人的运动范围
地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。 例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子?
 
package arrays;

public class movingCount_JZ66 {

    public static void main(String[] args) {
        System.out.println(movingCount(2,3,3));
        
    }
    public static int movingCount(int threshold, int rows, int cols){
        boolean[][] flag = new boolean[rows][cols];
         return  move(0,0,threshold,rows,cols,flag);
         
      
   }
   public static int move(int i,int j,int threshold, int rows, int cols,boolean[][] flag){
       if(i<0||i>=rows||j<0||j>=cols||sum(i)+sum(j)>threshold||flag[i][j]==true)return 0;
       flag[i][j]=true;
       return move(i,j-1,threshold,rows,cols,flag)
      + move(i,j+1,threshold,rows,cols,flag)
       +move(i-1,j,threshold,rows,cols,flag)
      + move(i+1,j,threshold,rows,cols,flag)+1;
       
   }
   public static int sum(int i){
       int res=0;
       while(i!=0){
            res+=i%10;
           i/=10;
       }
       return res;
   }

}

3. 单词搜索(二维数组)

给定一个二维网格和一个单词,找出该单词是否存在于网格中。

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

示例:

board =
[
  [‘A‘,‘B‘,‘C‘,‘E‘],
  [‘S‘,‘F‘,‘C‘,‘S‘],
  [‘A‘,‘D‘,‘E‘,‘E‘]
]

给定 word = "ABCCED", 返回 true
给定 word = "SEE", 返回 true
给定 word = "ABCB", 返回 false
package leetcode;

public class wordSearch_80 {

    public static void main(String[] args) {
        char[][] board = { { A, B, C, E }, { S, F, E, S }, { A, D, E, E } };
        String word = "ABE";
        System.out.println(exist(board, word));
    }

    public static boolean exist(char[][] board, String word) {
        int m = board.length;
        int n = board[0].length;
        boolean[][] flag = new boolean[m][n];
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (find(i, j, board, word, 0, flag)) {
                    return true;
                }
            }
        }
        return false;
    }

    public static boolean find(int i, int j, char[][] board, String word, int x, boolean[][] flag) {
        if (i < 0 || j < 0 || i >= board.length || j >= board[0].length || word.charAt(x) != board[i][j]
                || flag[i][j] == true)
            return false;
        if (x == word.length() - 1)
            return true;
        flag[i][j] = true;
        if (find(i - 1, j, board, word, x + 1, flag) || find(i + 1, j, board, word, x + 1, flag)
                || find(i, j - 1, board, word, x + 1, flag) || find(i, j + 1, board, word, x + 1, flag)) {
            return true;
        }
        flag[i][j] = false;
        return false;
    }

}

4、矩阵中的路径(和第3题一样,区别是给出的是一维数组)

请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。 例如技术图片

矩阵中包含一条字符串"bcced"的路径,但是矩阵中不包含"abcb"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。
public class Solution {
    public boolean hasPath(char[] matrix, int rows, int cols, char[] str)
    {
        //标志位,初始化为false
        boolean[] flag = new boolean[matrix.length];
        for(int i=0;i<rows;i++){
            for(int j=0;j<cols;j++){
                 //循环遍历二维数组,找到起点等于str第一个元素的值,再递归判断四周是否有符合条件的----回溯法
                 if(judge(matrix,i,j,rows,cols,flag,str,0)){
                     return true;
                 }
            }
        }
        return false;
    }
     
    //judge(初始矩阵,索引行坐标i,索引纵坐标j,矩阵行数,矩阵列数,待判断的字符串,字符串索引初始为0即先判断字符串的第一位)
    private boolean judge(char[] matrix,int i,int j,int rows,int cols,boolean[] flag,char[] str,int k){
        //先根据i和j计算匹配的第一个元素转为一维数组的位置
        int index = i*cols+j;
        //递归终止条件
        if(i<0 || j<0 || i>=rows || j>=cols || matrix[index] != str[k] || flag[index] == true)
            return false;
        //若k已经到达str末尾了,说明之前的都已经匹配成功了,直接返回true即可
        if(k == str.length-1)
            return true;
        //要走的第一个位置置为true,表示已经走过了
        flag[index] = true;
         
        //回溯,递归寻找,每次找到了就给k加一,找不到,还原
        if(judge(matrix,i-1,j,rows,cols,flag,str,k+1) ||
           judge(matrix,i+1,j,rows,cols,flag,str,k+1) ||
           judge(matrix,i,j-1,rows,cols,flag,str,k+1) ||
           judge(matrix,i,j+1,rows,cols,flag,str,k+1)  )
        {
            return true;
        }
        //走到这,说明这一条路不通,还原,再试其他的路径
        flag[index] = false;
        return false;
    }
 
 
}

 

 
 

以上是关于剑指offer的主要内容,如果未能解决你的问题,请参考以下文章

剑指 Offer(第 2 版)完整题解笔记 & C++代码实现(LeetCode版)

LeetCode(剑指 Offer)- 14- I. 剪绳子

LeetCode(剑指 Offer)- 14- I. 剪绳子

剑指offer——第二十九天(动态规划“困难”)

剑指 Offer 45. 把数组排成最小的数 剑指 Offer 61. 扑克牌中的顺子 剑指 Offer 40. 最小的k个数

剑指 offer 刷题记录