【Day14】每天三算法

【Day14】每天三算法

题目

NC16 对称的二叉树

描述

描述

思考

咱们考虑用递归的思想解决这道题

如果要满足题目给出的要求,不难发现我们需要满足的条件如下:

left.val == right.val
left.left.val == right.right.val
left.right.val == right.left.val

了解这些条件后,我们的递归代码就不难给出了

题解

这里要注意所有可能的递归终止调价

public class Solution {
    public boolean isSymmetrical(TreeNode pRoot) {
        if (pRoot==null) return true;
        return dfs(pRoot.left,pRoot.right);
    }

    public boolean dfs(TreeNode left,TreeNode right) {
        if (left==null && right==null) return true;
        if (left==null || right==null) return false;
        if (left.val!=right.val) return false;
        return dfs(left.left,right.right) && dfs(left.right,right.left);
    }
}

NC26 括号生成

描述

描述

思考

这道题我们可以用回溯的思路来解决

当 n=3 时,观察所有的括号生成式

((())), (()()), (())(), ()(()), ()()()

可以发现,每个位置,一定是保证左括号个数大于或等于右括号的

但是最后,左括号个数一定要和右括号个数相等

示例

题解
public class NC26_generateParenthesis {
    public ArrayList<String> generateParenthesis (int n) {
        ArrayList<String> res = new ArrayList<>();
        backTrack(n,n,new StringBuilder(),res);
        return res;
    }

    public void backTrack(int ls,int rs,StringBuilder track,ArrayList<String> res) {
        // 递归终止条件
        if (ls==0 && rs==0) {
            res.add(track.toString());
            return;
        }
        if (ls==rs) {
            track.append("(");
            backTrack(ls-1,rs,track,res);
            track.replace(track.length()-1,track.length(),"");
        } else {
            if (ls>0) {
                track.append("(");
                backTrack(ls-1,rs,track,res);
                track.replace(track.length()-1,track.length(),"");
            }
            track.append(")");
            backTrack(ls,rs-1,track,res);
            track.replace(track.length()-1,track.length(),"");
        }
    }
}
小结

这道题虽然在牛客上标榜中等难度题目,但其实只要借助回溯算法,就可以很轻松的解出

这里还要提醒各位一句,80% 的题,如果没有思路,借助回溯或者利用回溯的思想,肯定能写出来

所以遇到回溯的题希望各位重视起来

NC18 顺时针旋转矩阵

描述

描述

示例:

输入:
[[1,2,3],
 [4,5,6],
 [7,8,9]],3 

返回:
[[7,4,1],
 [8,5,2],
 [9,6,3]]
思考

方法1:

对于阶为3的矩阵,我们可以观察一下不同坐标旋转以后的规律

(0,0) -> (0,2)
(0,1) -> (1,2)
(0,2) -> (2,2)
(1,0) -> (0,1)

可以发现有如下规律:

(i,j) -> (j,n-i-1)

那么思路就比较明显了,我们可以再开辟一个新的矩阵空间,然后遍历原矩阵,重新计算每个坐标在新矩阵的新坐标,然后进行赋值

方法2:

还有一个,就是矩阵旋转的标准做法了

对于顺时针旋转90度,我们可以让它先沿主对角线翻转,然后在左右翻转

图示

借助初中几何,我们可以计算出用这种方法,转换后的坐标是多少

这里要注意,因为我们的坐标是从0开始的,所以最后我们那个n 要-1,也就算出了纵坐标是 n-1-i

题解

方法1:

创建新的空间,然后用公式计算每个坐标的新坐标进行替换

public class Solution {
    public int[][] rotateMatrix(int[][] mat, int n) {
        if (mat==null || mat.length==0) return null;
        int[][] res = new int[mat.length][mat[0].length];
        for (int i = 0; i < mat.length; i++) {
            for (int j = 0; j < mat[0].length; j++) {
                res[j][n-i-1] = mat[i][j];
            }
        }
        return res;
    }
}

方法2:

使用矩阵转换的坐标性质

public class Solution {
    public int[][] rotateMatrix(int[][] mat, int n) {
        // 主对角线反转
        for (int i = 0; i < n; i++) {
            for (int j = i; j < n; j++) {
                swap(mat,i,j,j,i);
            }
        }
        // 左右反转
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n / 2; j++) {
                swap(mat,i,j,i,n-j-1);
            }
        }
        return mat;
    }

    private void swap(int[][]mat,int x1,int y1,int x2,int y2) {
        int tmp = mat[x1][y1];
        mat[x1][y1]=mat[x2][y2];
        mat[x2][y2]=tmp;
    }
}
小结

这道题的代码不难,其实只涉及基础的循环分支语句

主要是想到合理的矩阵旋转的算法比较麻烦

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FARO_Z

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值