题一:【矩阵中的路径】
请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。 例如 a b c e s f c s a d e e 矩阵中包含一条字符串"bcced"的路径,但是矩阵中不包含"abcb"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。
分析:回溯DFS???需要设置一个flag数组标志是否已经遍历过。如果当前数组当前元素相等,则比较下一个元素(上下左右4种可能,但实际只有3种,只要有一个满足即可)。
1 public class Solution { 2 public boolean hasPath(char[] matrix, int rows, int cols, char[] str) 3 { 4 if(str.length>rows*cols) return false; 5 //标志位,标志数组内某位置元素是否已经在走过的路径中,默认为false 6 boolean[] flag = new boolean[matrix.length]; 7 for(int i=0;i<rows;i++){ 8 for(int j=0;j<cols;j++){ 9 int k = 0;//str进行比较的位置索引 10 //先判断第一个元素减少点时间 11 if(matrix[i*cols+j]==str[k]&&judgeNext(matrix,i,j,k,rows,cols,str,flag)){ 12 return true; 13 } 14 } 15 } 16 return false; 17 } 18 public boolean judgeNext(char[] matrix, int i, int j, int k, int rows, int cols, char[] str, boolean[] flag){ 19 int index = i*cols+j; 20 if(i<0||i>=rows|| 21 j<0||j>=cols|| 22 matrix[index]!=str[k]||//判断是否相等 23 flag[index]==true) //表示不能重走已经走过的路径 24 { 25 return false; 26 } 27 flag[index]=true;//表示当前位置元素正在走,或者是试探性走。置为true,让依照本元素走的路径不在重走本元素。 28 if(k==str.length-1) return true;//走完了 29 if(judgeNext(matrix,i-1,j,k+1,rows,cols,str,flag)|| 30 judgeNext(matrix,i+1,j,k+1,rows,cols,str,flag)|| 31 judgeNext(matrix,i,j-1,k+1,rows,cols,str,flag)|| 32 judgeNext(matrix,i,j+1,k+1,rows,cols,str,flag)) 33 { 34 return true; 35 } 36 flag[index]=false;//如果没有走到这步说明当前位置元素满足条件。如果走到这步说明不符合条件,需要重新置为false。 37 return false; 38 } 39 40 }
题二:【机器人的运动范围】
地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。 例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子?
分析:和上题类似,定义一个flag二维数组,记录是否移动过
1 public class Solution { 2 public int movingCount(int threshold, int rows, int cols) 3 { 4 int[][] flag = new int[rows][cols];//默认全是0 5 return countCell(0,0,threshold,rows,cols,flag); 6 } 7 public int countCell(int i, int j, int threshold, int rows, int cols, int[][] flag){ 8 if(i<0||i>=rows|| 9 j<0||j>=cols|| 10 judge(i,j,threshold)==false|| 11 flag[i][j]==1) 12 { 13 return 0; 14 } 15 flag[i][j] = 1; 16 return countCell(i+1,j,threshold,rows,cols,flag)+ 17 countCell(i-1,j,threshold,rows,cols,flag)+ 18 countCell(i,j+1,threshold,rows,cols,flag)+ 19 countCell(i,j-1,threshold,rows,cols,flag)+1; 20 } 21 /** 22 判断当前格子是否满足要求 23 */ 24 public boolean judge(int i, int j, int threshold){ 25 int remainder1=0, remainder2=0; 26 while(i!=0){ 27 remainder1 += i%10;//各位和 28 i = i/10; 29 } 30 while(j!=0){ 31 remainder2 += j%10; 32 j = j/10; 33 } 34 if(remainder1+remainder2<=threshold){ 35 return true; 36 }else{ 37 return false; 38 } 39 } 40 }
题三:【剪绳子】
给你一根长度为n的绳子,请把绳子剪成整数长的m段(m、n都是整数,n>1并且m>1),每段绳子的长度记为k[0],k[1],...,k[m]。请问k[0]xk[1]x...xk[m]可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。输入一个数n,意义见题面。(2 <= n <= 60),输出答案。例如输入:8,输出:18.
分析:根据题意,找出乘积最大的m个数(这m个数的和为n)。
法一:DP:f(n) = max{ f(i) * f(n-i) },n剪成i和n-i两大段,其中f(i),f(n-i)再次划分成两小段,将大问题不断划分成小问题。需要定义一个数组,表示长度为i时的最佳分段的乘积(即最大乘积).
1 public class Solution { 2 public int cutRope(int target) { 3 if(target<2) return 0; 4 if(target==2) return 1; 5 if(target==3) return 2; 6 //temp数组中第i个元素表示把长度为i的绳子分成若干段之后的最大乘积 7 //0,1,2,3位置上设置值便于计算 8 int[] temp = new int[target+1]; 9 temp[0] = 0; 10 temp[1] = 1; 11 temp[2] = 2; 12 temp[3] = 3; 13 for(int i=4;i<target+1;i++){//填写数组,当长度为i时的最佳选择 14 int max = 0; 15 for(int j=1;j<=i/2;j++){//j<i/2是因为 4分成1、3和3、1是一样的 16 int product = temp[j]*temp[i-j]; 17 if(max<product){ 18 max = product; 19 } 20 } 21 temp[i]=max; 22 } 23 return temp[target];//temp最后一个元素就是当i=target时的最佳选择 24 } 25 }
法:贪婪:
n=4 2*2
n=5 2*3
n=6 3*3
n=7 3*2*2
n=8 3*3*2
n=9 3*3*3
当x>5时,2*(x-2)>x,3*(x-3)>x,因此,一个长度为n的一段绳子最好能划分成2或3,又因为3*(x-3)>2*(x-2),因此要尽可能多的划分成3.例如当n=11时,3*(11-3)>11,3*(8-3)>8,3*(5-3)>5,因此n=11时,划分过程为3、8—3、3、5——3、3、3、2。注意:当x等于4的时候,最佳剪成2+2。
1 import java.lang.Math; 2 public class Solution { 3 public int cutRope(int target) { 4 if(target<2) return 0; 5 if(target==2) return 1; 6 if(target==3) return 2; 7 int timesOfTwo=0,timesOfThree=0; 8 timesOfThree = target/3; 9 if((target-3*(timesOfThree-1))==4){ 10 timesOfThree -= 1; 11 } 12 timesOfTwo = (target-timesOfThree*3)/2; 13 return (int)(Math.pow(2,timesOfTwo)*Math.pow(3,timesOfThree)); 14 } 15 }