51. N皇后(困难)
回溯
思路:
- 按行添加皇后,所以行不会发生冲突
- ArrayList currentQueen,这个是用来存列的index,用一个简单的条件判断语句就能使得currentQueen中不含相同的值,即不发生列冲突
- 那怎么避免对角线冲突呢?这里需要一个小技巧,isDiagonalAttack就是用来判断是否发生对角线冲突的,获取当前所在行和列,遍历在此之前的每一行,因为之前每一行都是存了currentQueen的值的,所以只要遍历过程判断只要有任意一行的点和当前点满足对角线(横坐标纵坐标的差值相等),那么就发生了对角线冲突
public List<List<String>> solveNQueens(int n) {
List<List<String>> res = new ArrayList<>();
if(n == 0) return res;
backtrace(new ArrayList<Integer>(),res,n);
return res;
}
public void backtrace(ArrayList<Integer> currentQueen,List<List<String>> res,int n){
// 当前皇后的个数是否等于 n 了,等于的话就加到结果中
if(currentQueen.size() == n){
List<String> temp = new ArrayList<>();
for (int i = 0; i < n; i++) {
char[] t = new char[n];
Arrays.fill(t,'.');
t[currentQueen.get(i)] = 'Q';
temp.add(new String(t));
}
res.add(temp);
return;
}
//尝试每一列
for (int col = 0; col < n; col++) {
//查看列是否冲突
if(currentQueen.contains(col)){
continue;
}
//判断对角线是否冲突
if(isDiagonalAttack(currentQueen,col)){
continue;
}
currentQueen.add(col);
backtrace(currentQueen,res,n);
//回溯
currentQueen.remove(currentQueen.size() - 1);
}
}
public boolean isDiagonalAttack(ArrayList<Integer> currentQueen, int col){
int current_row = currentQueen.size();
int current_col = col;
for (int row = 0; row < currentQueen.size(); row++) {
if(Math.abs(current_row - row) == Math.abs(current_col - currentQueen.get(row))){
return true;
}
}
return false;
}
52. N皇后
和51题一样,改个输出就行了
public int totalNQueens(int n) {
List<Integer> res = new ArrayList<>();
if(n == 0) return 0;
backtrace(new ArrayList<Integer>(),res,n);
return res.size();
}
public void backtrace(ArrayList<Integer> currentQueen,List<Integer> res,int n){
// 当前皇后的个数是否等于 n 了,等于的话就加到结果中
if(currentQueen.size() == n){
res.add(1);
return;
}
//尝试每一列
for (int col = 0; col < n; col++) {
//查看列是否冲突
if(currentQueen.contains(col)){
continue;
}
//判断对角线是否冲突
if(isDiagonalAttack(currentQueen,col)){
continue;
}
currentQueen.add(col);
backtrace(currentQueen,res,n);
//回溯
currentQueen.remove(currentQueen.size() - 1);
}
}
public boolean isDiagonalAttack(ArrayList<Integer> currentQueen, int col){
int current_row = currentQueen.size();
int current_col = col;
for (int row = 0; row < currentQueen.size(); row++) {
if(Math.abs(current_row - row) == Math.abs(current_col - currentQueen.get(row))){
return true;
}
}
return false;
}
53. 最大子序和
动态规划
public int maxSubArray_dp(int[] nums) {
int n = nums.length;
int[] dp = new int[n];
int max = nums[0];
dp[0] = nums[0];
for (int i = 1; i < n; i++) {
if(dp[i - 1] < 0){
dp[i] = nums[i];
}else{
dp[i] = dp[i - 1] + nums[i];
}
max = Math.max(max,dp[i]);
}
return max;
}
动态规划优化
上面dp[i]仅和dp[i-1]和nums[i]有关,可以优化空间复杂度
public int maxSubArray(int[] nums) {
int ans = nums[0];
int sum = 0;
for (int num : nums) {
if (sum > 0) {
sum += num;
} else {
sum = num;
}
ans = Math.max(sum, ans);
}
return ans;
}
**
54. 螺旋矩阵
剑指里面也有道差不多的题
public List<Integer> spiralOrder(int[][] matrix) {
List<Integer> res = new ArrayList<>();
if(matrix==null||matrix.length==0||matrix[0].length==0) return res;
int left=0;
int right=matrix[0].length-1;
int top=0;
int bottom=matrix.length-1;
while (true){
for(int i=left;i<=right;i++){
res.add(matrix[top][i]);
}
if(++top>bottom) break;
for(int j=top;j<=bottom;j++){
res.add(matrix[j][right]);
}
if(--right<left) break;
for(int k=right;k>=left;k--){
res.add(matrix[bottom][k]);
}
if(--bottom<top) break;
for(int l=bottom;l>=top;l--){
res.add(matrix[l][left]);
}
if(++left>right) break;
}
return res;
}
55. 跳跃游戏
借鉴45题,去掉steps
顺藤摸瓜
public boolean jump(int[] nums) {
int end = 0;
int maxposition = 0;
for(int i = 0;i < nums.length - 1;i++){
if(i > end){
return false;
}
//找能跳到最远的
maxposition = Math.max(maxposition, nums[i] + i);
if(i == end){
//遇到end边界,就更新边界,并且步数+1
end = maxposition;
}
}
return maxposition >= nums.length - 1;
}
直接判断下标
更新一个最大可达的位置
public boolean canJump(int[] nums) {
int reach = 0;//能到达最远的引索
int length = nums.length;
for (int i = 0; i < length; i++) {
//如果当前遍历的位置连reach都达不到,返回false
if (i > reach) {
return false;
} else {//否则我们就去更新我们的reach
reach = Math.max(i + nums[i], reach);
}
}
return true;
}