剑指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 45. 把数组排成最小的数 剑指 Offer 61. 扑克牌中的顺子 剑指 Offer 40. 最小的k个数