一刷的入口
10-1. 斐波那契数列
见一刷
10-2.青蛙跳台阶问题
见一刷
11. 旋转数组的最小数字
见一刷,本题最佳写法是二分法。
本题要注意的是,Leetcode上有[1,3,5]这样的测试用例,导致一刷的写法1不能通过。因此此处提出修改。因为牛客博客还没有解决再次编辑的时候出现的转义,只能在这里修改了。
在Leetcode上ac的:
class Solution { public int minArray(int[] numbers) { for (int i = 1; i < numbers.length; i++) { if (numbers[i] < numbers[i - 1]) { return numbers[i]; } } return numbers[0]; } }
最优二分写法:
如果你和最右边的j比较,那么你应该让j--,如果你和最左边的i比较,则最后一个else应该是i++。
public class Solution2 { public int minArray(int[] numbers) { int i = 0; int j = numbers.length-1; while(i<j){ int m = (i+j)/2; if(numbers[m]>numbers[j]){//说明m在左边增长数组中,此时旋转点在(m,j] i = m+1; }else if(numbers[m]<numbers[j]){//说明在右边增长数组中,此时旋转点在[i,m] j = m; }else {//相等了,因此需要缩减范围重新比较 j--; } } return numbers[i]; } }
12 矩阵中的路径
一刷学习别人的题解中,使用了压缩空间的技巧,这里记录最直观的回溯法,二维的写法。
首先要理解回溯,到了某个节点,就标记到了,如果要回退,则将标记改回去。
这题可以理解成一个标准的回溯模板题。
public class Solution { public boolean exist(char[][] board, String word) { if (board == null || board[0] == null || board.length == 0 || board[0].length == 0 || word == null || word.equals("")) { return false; } boolean[][] isVisited = new boolean[board.length][board[0].length]; char[] chs = word.toCharArray(); for (int i = 0; i < board.length; i++) { for (int j = 0; j < board[0].length; j++) { if (board[i][j] == chs[0]) { if (bfs(board, i, j, isVisited, chs, 0)) return true; } } } return false; } private boolean bfs(char[][] board, int i, int j, boolean[][] isVisited, char[] chs, int index) { if (index == chs.length) { return true; } if (i < 0 || j < 0 || i == board.length || j == board[0].length || isVisited[i][j] || board[i][j] != chs[index]) { return false; } isVisited[i][j] = true; boolean res = bfs(board, i + 1, j, isVisited, chs, index + 1) || bfs(board, i - 1, j, isVisited, chs, index + 1) || bfs(board, i, j + 1, isVisited, chs, index + 1) || bfs(board, i, j - 1, isVisited, chs, index + 1); isVisited[i][j] = false; return res; } }
13. 机器人的运动范围
可以好好理解本题的深度遍历和上题的回溯法的区别。深度遍历一般是你进入某个位置后,这个位置就定死了,或者说,不用再回到这个地方了,因为我已经遍历了。而回溯不同,回溯是我前面的路走不通后,要回来再尝试其他路。回溯的目的性更强,找到某个序列,而遍历只要到了即可。因此,回溯需要反复改标记,而遍历只需要改动一次标记。
public class Solution { public int movingCount(int m, int n, int k) { if (n <= 0 || k < 0 || m <= 0) return 0; if(k==0) return 1; boolean[][] isVisited = new boolean[m][n];//标记 int count = movingCountCore(k, m, n, 0, 0, isVisited); return count; } private int movingCountCore(int threshold,int rows,int cols, int row,int col, boolean[][] isVisited) { if (row < 0 || col < 0 || row >= rows || col >= cols || isVisited[row][col] || cal(row) + cal(col) > threshold) return 0; isVisited[row][col] = true; return 1 + movingCountCore(threshold, rows, cols, row - 1, col, isVisited) + movingCountCore(threshold, rows, cols, row + 1, col, isVisited) + movingCountCore(threshold, rows, cols, row, col - 1, isVisited) + movingCountCore(threshold, rows, cols, row, col + 1, isVisited); } private int cal(int num) { int sum = 0; while (num > 0) { sum += num % 10; num /= 10; } return sum; } }
14.1 减绳子
同样,可以直接参考一刷的题解。一刷记录了两个思路,建议看一刷
记录Leetcode上的ac:
class Solution { public int cuttingRope(int n) { if (n <= 1)//绳长1或者0执行剪操作 return 0; if (n == 2)//绳长2执行剪操作 return 1; if (n == 3)//绳长3执行剪操作 return 2; int[] product = new int[n + 1]; // 用于存放最大乘积值 product[2] = 2;//剩余绳长为2可形成的最大乘积(可剪可不剪,不减就是直接拿2最大) product[3] = 3;//剩余绳长为3可形成的最大乘积(可剪可不剪,不减就是直接拿3最大) // 开始从下到上计算长度为i绳子的最大乘积值product[i] for (int i = 4; i <= n; i++) { for (int j = 2; j <= i / 2; j++) {//j到i/2即可,从i/2到i并不会更新最大值 product[i]=Math.max(product[i],product[j] * product[i - j]); } } return product[n]; } }
14.2 减绳子
思路和一刷的思路2相似,只是多了一个取余
public class Solution { public int cuttingRope(int n) { if(n == 2) return 1; if(n == 3) return 2; long res = 1; while(n > 4){ res *= 3; res = res % 1000000007; n -= 3; } return (int)(res * n % 1000000007); } }
15.二进制中1的个数
一刷中记录的解法比较全。
这里记录一个ac的方法
这里需要说明。java中的>>>是无符号数的右移,如果用>>则会出错。
public class Solution { // you need to treat n as an unsigned value public int hammingWeight(int n) { int count = 0; while (n != 0) { if ((n & 1) == 1) { count++; } n = n >>> 1;//把n的2进制形式往右推一位 } return count; } }
解法2:(一刷上的思路3)
public class Solution { // you need to treat n as an unsigned value public int hammingWeight(int n) { int count = 0; while(n!= 0){ count++; n = n & (n - 1); } return count; } }