你未必出类拔萃,但一定与众不同
剑指offer 12-16
题12 矩阵中的路径
给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
例如,在下面的 3×4 的矩阵中包含单词 “ABCCED”(单词中的字母已标出)
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/ju-zhen-zhong-de-lu-jing-lcof
public boolean exist(char[][] board, String word) {
if (board == null || board.length == 0 || board[0].length == 0) {
return false;
}
//拆分字符串为一个一个字符
char[] chars = word.toCharArray();
//定义一个boolean数组 判断当前的节点是否走过
boolean[][] visited = new boolean[board.length][board[0].length];
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board[0].length; j++) {
//从左边第一个点挨个去找路径
if (dfs(board, chars, visited, i, j, 0)) {
return true;
}
}
}
return false;
}
//开始进行dfs深搜
private boolean dfs(char[][] board, char[] chars, boolean[][] visited, int i, int j, int start) {
if (i < 0 || i >= board.length || j < 0 || j >= board[0].length
|| chars[start] != board[i][j] || visited[i][j]) {
return false;
}
if (start == chars.length - 1) {
return true;
}
visited[i][j] = true;
boolean ans = false;
ans = dfs(board, chars, visited, i + 1, j, start + 1)
|| dfs(board, chars, visited, i - 1, j, start + 1)
|| dfs(board, chars, visited, i, j + 1, start + 1)
|| dfs(board, chars, visited, i, j - 1, start + 1);
//这里需要复位是因为 如果这条路线走不通 那么需要把走过的位置都复位,方便下一次重新开始
//如果直接找到了路径 就会直接返回true
visited[i][j] = false;
return ans;
}
题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。请问该机器人能够到达多少个格子?
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/ji-qi-ren-de-yun-dong-fan-wei-lcof
思路:
- 可以将这个方格也看做一个矩阵
- 机器人能够正式进入格子 需要进行判断 也就是 i j 的数位相加必须小于等于 k的值
- 机器人进入格子开始移动的时候,从坐标[0,0] 开始移动 此时他可以选择 向右或者 向下移动 事实上此时边界就出来了 因为 机器人如果在中间位置 可以 左右上下移动
- 设置一个boolean类型的二维数组来进行判断 是否都经过了这个坐标的位置 防止重复移动。
- 然后通过将经过的路径相加 就可得到
class Solution {
public static int movingCount(int m, int n, int k) {
int[][] number = new int[m][n];
boolean[][] visited = new boolean[number.length][number[0].length];
int result = dfs(number,k,visited,0,0);
return result;
}
public static int dfs(int[][] number,int k,boolean[][] visited,int i,int j){
if(i < 0 || j < 0 || i >= number.length || j >= number[0].length || visited[i][j]){
return 0;
}
int count = 0;
if(sum(i,j) <= k){
visited[i][j] = true;
count = 1 + dfs(number,k,visited,i+1,j)
+dfs(number,k,visited,i,j+1)
+dfs(number,k,visited,i-1,j)
+dfs(number,k,visited,i,j -1);
}
return count;
}
public static int sum(int a,int b){
int sum1 = 0;
int sum2 = 0;
while(a > 0){
sum1 += a % 10;
a = a/10;
}
while(b > 0){
sum2 += b % 10;
b = b/10;
}
return sum1 + sum2;
}
}
题14 剪绳子
给你一根长度为 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。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/jian-sheng-zi-lcof
思路:
-
这道题有点难,当时没有头绪,然后就自己把 绳子长写出来
4 : 2 * 2 = 1 * 3
5 :2 * 3
6 :3* 3
7:3*4
8:3* 3*2
9:3 * 3 * 3
慢慢推导 发现拆分成3 值是最大的 4 那个就是 2 2 大于3 其他7的话就是 3 * 4 8= 3 3 *2 当时没想到为啥 后面看了解法才发现里面还有求极值
-
然后就是求当前绳长的两个因素 一个是除出来的商 一个就是余数
-
余数为0 的时候 就是刚好是 3 * 3连续乘法
-
余数为1 的时候 就是余数为4 也就是拆分前面的那个 4 : 2 *2 > 1 *3
-
余数为2 的时候 就是3 * 3 连乘 乘以余数2
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);
}
if(b == 1){
return (int) Math.pow(3 , a - 1) * 4;
}
return (int)Math.pow(3 , a) * 2;
}
}
题15 二进制中1的个数
编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 ‘1’ 的个数(也被称为 汉明重量).)。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/er-jin-zhi-zhong-1de-ge-shu-lcof
思路:
采用&运算
0 & 0 = 0;
0 & 1 = 0;
1 & 1 = 1;
使用与运算 让n的最低位每次都与1做与运算 低位若为1则结果1 不为1 则结果为0
>>>表示无符号右移,也叫逻辑右移,即若该数为正,则高位补0,而若该数为负数,则右移后高位同样补0。
然后再使 n 右移一位即可 使用>>> 再进行比较
public class Solution {
// you need to treat n as an unsigned value
public int hammingWeight(int n) {
int number = 0;
while(n != 0){
if((n & 1) == 1){
number ++;
}
n = n >>>1;
}
return number;
}
}
题16 数值的整数次方
实现 pow(x, n) ,即计算 x 的 n 次幂函数(即,xn)。不得使用库函数,同时不需要考虑大数问题。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/shu-zhi-de-zheng-shu-ci-fang-lcof
思路:
当指数为负数时, 先对指数求绝对值,然后再取当前需要求的数的倒数
通过循环 result负责确定最终结果的正负。
class Solution {
public double myPow(double x, int n) {
long flag = n;
double result = 1.0;
if(n == 0){
return 1;
}
if(x == 1){
return x;
}
if(flag < 0){
flag = -flag;
x = 1/x;
}
while(flag > 0) {
//判断当前的数是否是奇数
if((flag & 1) == 1){
result = result * x;
}
x = x * x;
//右移运算符代替2
flag = flag >> 1;
}
return result;
}
}