zoukankan      html  css  js  c++  java
  • [leetcode] Number of Boomerangs

    Given n points in the plane that are all pairwise distinct, a "boomerang" is a tuple of points (i, j, k) such that the distance between iand j equals the distance between i and k (the order of the tuple matters).

    Find the number of boomerangs. You may assume that n will be at most 500 and coordinates of points are all in the range [-10000, 10000] (inclusive).

    Example:

    Input:
    [[0,0],[1,0],[2,0]]
    
    Output:
    2
    
    Explanation:
    The two boomerangs are [[1,0],[0,0],[2,0]] and [[1,0],[2,0],[0,0]]

     分析:题目意思理解起来并不是很难,二维数组的每一行代表平面上的一个点,任意一个点到其他两个点距离相同时,视为一个解。这里要注意的是其他两个点也是分先后顺序的,也就是可以看成是一个排列问题。有了这个作为基础,首先想到的就是计算所有点之间的距离,并且用一个二维矩阵保存下来。然后去遍历这个二维矩阵的每一行,假设一行有m个相同距离为1的点,那么就是A(m,2)。
            有了上面的分析,首先想到找排列公式,在网上找了一个递归版本的求排列和组合的代码,用java描述如下:
     1     /**
     2      * 计算阶乘数,即n! = n * (n-1) * ... * 2 * 1 
     3      * @param n
     4      * @return
     5      */
     6     private static long factorial(int n) {
     7         long sum = 1;
     8         while( n > 0 ) {
     9             sum = sum * n--;
    10         }
    11         return sum;
    12     }
    13     /**
    14      * 排列计算公式A<sup>m</sup><sub>n</sub> = n!/(n - m)!
    15      * @param m
    16      * @param n
    17      * @return
    18      */
    19     public static long arrangement(int m, int n) {
    20         return m <= n ? factorial(n) / factorial(n - m) : 0;
    21     }
    22     /**
    23      * 组合计算公式C<sup>m</sup><sub>n</sub> = n! / (m! * (n - m)!)
    24      * @param m
    25      * @param n
    26      * @return
    27      */
    28     public static long combination(int m, int n) {
    29         return m <= n ? factorial(n) / (factorial(m) * factorial((n - m))) : 0;
    30     }

          那么本题的代码如下:

     1     int res = 0;
     2     public int numberOfBoomerangs(int[][] points) {
     3         int n = points.length;
     4         double[][] distance = new double[n][n];
     5         for ( int i = 0 ; i < n ; i ++ ){
     6             for ( int j = 0 ; j < n ; j ++ ){
     7                 distance[i][j] = Math.sqrt((points[j][0]-points[i][0])*(points[j][0]-points[i][0])+(points[j][1]-points[i][1])*(points[j][1]-points[i][1]));
     8             }
     9         }
    10         Map<Double,Integer> map = new HashMap<>();
    11         for ( int i = 0 ; i < n ; i ++ ){
    12             map.clear();
    13             for ( int j = 0 ; j < n ; j ++ ){
    14                 map.put(distance[i][j],map.getOrDefault(distance[i][j],0)+1);
    15             }
    16             for ( int value : map.values() ){
    17                 if ( value >= 2 ) calcnum(value);
    18             }
    19         }
    20         return res;
    21     }
    22     private void calcnum(int value) {
    23         res += factorial(value) / factorial(value-2);
    24     }
    25     private static long factorial(int n) {
    26         long sum = 1;
    27         while( n > 0 ) {
    28             sum = sum * n--;
    29         }
    30         return sum;
    31     }

          最后运行时间117ms,超过94.7%的人。


          但是,还是有很大的优化空间,首先在计算距离矩阵的时候,没必要先全部保存下来然后再遍历,可以一边计算,一边用Map记录;而且对于A(m,2),计算下来的结果就是m*(m-1),所以也没必要再用递归来做了;因为只要找距离相同的点的个数,也不需用求根号了;这样优化下来,第二版代码如下:

     1 class Solution {
     2     public int numberOfBoomerangs(int[][] points) {
     3         int res = 0;
     4         Map<Double,Integer> map = new HashMap<>();
     5         int n = points.length;
     6         for ( int i = 0 ; i < n ; i ++ ){
     7             for ( int j = 0 ; j < n ; j ++ ){
     8                 double d = (points[j][0]-points[i][0])*(points[j][0]-points[i][0])+(points[j][1]-points[i][1])*(points[j][1]-points[i][1]);
     9                 map.put(d,map.getOrDefault(d,0)+1);
    10             }
    11             for ( int value : map.values() ){
    12                 if ( value >= 2 ) res += value*(value-1);
    13             }
    14             map.clear();
    15         }
    16         return res;
    17     }
    18 }

          运行时间97ms,超过99%的人。

  • 相关阅读:
    关于使用wcf架构分布式系统的一点想法
    vs2012 远程调试服务器上iis下的程序
    F#定义方法参数
    产生不重复的随机数
    巧在C#中设置多维动态数组,可以动态增加及删除
    C#时间相减
    css控制图片大小的方法
    常用网络命令
    DEDE SQL 常用语句
    未审核文档发布时间的自动更改方法for DEDEcms v5.3(修正版)
  • 原文地址:https://www.cnblogs.com/boris1221/p/9289642.html
Copyright © 2011-2022 走看看