Leetcode刷题(回旋镖、打家劫舍)

个人笔记推荐

最近将之前学习的多线程的相关知识进行了总结以及对于juc相关的并发编程的api进行了复习,学习java的小伙伴可以提供一些意见:个人JUC笔记

题目一描述

回旋镖数量: 给定平面上n对不同的点,"回旋镖"是由点表示的元祖(i,j,k),其中i和j之间的距离和i和k之间的距离相等

例如:
输入: [[0,0],[1,0],[2,0]]
输出为:2
可以组成两个回旋镖,[[1,0],[0,0],[2,0]]和[[1,0],[2,0],[0,0]]

传送门

题目一分析

该问题是一个选取点的问题,当确定一个点后需要确定另外两个点的位置,因此从剩余n个点中选取两个点,相当于排列组合的过程,由于位置相关,因此是一个n*(n-1),将除数相抵消的过程。
一开始写的是三层循环,因为一个回旋镖是一个三个点组成的元祖,循环找到距离相等且不同位置的点,但由于其时间复杂度比较高,不能通过测试。

代码如下
class Solution {
    public int numberOfBoomerangs(int[][] points) {
       //计算相同的总个数
       int count=0;
       //选取第一个点
        for(int i=0;i<points.length;i++){
            Map<Double,Integer> map = new HashMap<>();
            //选取第二个点,map中存储
            for(int j = 0;j<points.length;j++){
            //第一个点和第二个点不是同一个点计算他们的距离
            //计算有多少个点的距离是相同的相当于排列组合的一个过程
                if(j!=i){
                    double temp = getDis(points[i],points[j]);
                    if(!map.containsKey(temp)) map.put(temp,1);
                    else map.put(temp,map.get(temp)+1);
                }
            }
            //遍历集合
            Set<Map.Entry<Double, Integer>> entries = map.entrySet();
            for(Map.Entry<Double, Integer> entry:entries){
                if(entry.getValue()>1){
                    count=count+entry.getValue()*(entry.getValue()-1);
                }
            }
        }
        return count;
    }
    //计算两点之间的距离
    public static double getDis(int[] p1,int[] p2){
        double res = Math.sqrt(Math.pow((p1[0]-p2[0]),2)+Math.pow((p1[1]-p2[1]),2));
        return res;
    }
}
题目二描述

打家劫舍: 在上次打劫完一条街道之后和一圈房屋后,小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为“根”。 除了“根”之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果两个直接相连的房子在同一天晚上被打劫,房屋将自动报警。
计算在不触动警报的情况下,小偷一晚能够盗取的最高金额。
传送门

[3,2,3,null,3,null,null,1]
实例树结构
输出: 3+3+1 = 7

注:这么聪明的小偷,干啥不行!!!

题目二分析

对于树个人一般的解题思路是将左右分开看待,作为一个子树的子过程去解题,左树返回一个结果并且右树返回一个结果,当前的节点对于左右的结果都与自身节点的值相结合并进行处理交给上面的节点。
对于该题目

左子树返回其头结点对应的偷与不偷的金额结果
右子树返回其头结点对应偷与不偷的金额的结果
当前节点要是偷,那么左右节点都必须不偷才能进行
当前节点不偷,那么左右节点无论偷还是不偷都可以,因此是左边最大的金额+右边最大的金额
将以上信息封装交给上层节点处理

代码如下
class Solution {
    public int rob(TreeNode root) {
        if(root==null) return 0;
        //获取头结点的数据信息,返回其偷金额和不偷的金额中最大的那个
        Mydata value = getdata(root);
        int res = Math.max(value.tou,value.butou);
        return res;
    }
    //所有的节点都返回一个数据消息
    public Mydata getdata(TreeNode root){
        if(root==null) return new Mydata(root,0,0); 
        if(root.left==null&&root.right==null)return new Mydata(root,root.val,0);
        Mydata left = getdata(root.left);
        Mydata right = getdata(root.right);
        //当前节点能偷
        int temptou = root.val+left.butou+right.butou;
        //当前节点不能偷
        int tempbu = Math.max(left.tou,left.butou)+Math.max(right.tou,right.butou);
       
        return new Mydata(root,temptou,tempbu);
    }
}
//自定义消息封装体,返回当前节点以及自己偷该节点的最大值和不偷该节点的最大值
 class Mydata {
      TreeNode node;
      int tou ;
      int butou;
      public Mydata(TreeNode node,int tou,int butou){
        this.node = node ;
        this.tou = tou;
        this.butou = butou;
      }
 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值