leetcode 593. Valid Square

来源:互联网 发布:飞信网络技术开发公司 编辑:程序博客网 时间:2024/06/14 06:21

Given the coordinates of four points in 2D space, return whether the four points could construct a square.

The coordinate (x,y) of a point is represented by an integer array with two integers.

Example:

Input: p1 = [0,0], p2 = [1,1], p3 = [1,0], p4 = [0,1]Output: True

Note:

  1. All the input integers are in the range [-10000, 10000].
  2. A valid square has four equal sides with positive length and four equal angles (90-degree angles).
  3. Input points have no order.
就是看4个点是否构成的是正方形。

package leetcode;import java.util.Arrays;public class Valid_Square_593 {public boolean validSquare(int[] p1, int[] p2, int[] p3, int[] p4) {int[] allBian=new int[]{getDistance2(p1, p2),getDistance2(p1, p3),getDistance2(p1, p4),getDistance2(p2, p3),getDistance2(p2, p4),getDistance2(p3, p4)};Arrays.sort(allBian);if(allBian[0]==0){return false;}//保证有4个边相同,a^2可能比a大,也可能比a小if(allBian[0]==allBian[3]||allBian[2]==allBian[5]){//a^2比a大if(allBian[0]==allBian[3]){//使用勾股定理:a^2+b^2=c^2,而a=b,所以2a^2=c^2if(allBian[0]*2==allBian[5]){return true;}}else{//a^2比a小if(allBian[5]*2==allBian[0]){return true;}}}return false;}//返回距离的平方int getDistance2(int[] p1,int[] p2){int distance2=(p1[0]-p2[0])*(p1[0]-p2[0])+(p1[1]-p2[1])*(p1[1]-p2[1]);return distance2;}public static void main(String[] args) {// TODO Auto-generated method stubValid_Square_593 v = new Valid_Square_593();int[] p1 = new int[] { 0, 0 };int[] p2 = new int[] { 0, 0 };int[] p3 = new int[] { 0, 0 };int[] p4 = new int[] { 0, 0 };System.out.println(v.validSquare(p1, p2, p3, p4));}}
我为什么算距离的平方,而不是直接算距离呢?因为一个根号下去,变成double类型,有可能出现精度问题。如根号2=1.4142135623731...,但是1.4142135623731的平方=2.000000004,不等于2。

大神说:如果4点连成的是正方形,那么这4个点之间的6条线,一定有4条相等,另外2条也相等,且4条的长度不等于2条的长度。4条是边,2条是斜边。

public class Solution {    public boolean validSquare(int[] p1, int[] p2, int[] p3, int[] p4) {        HashMap<Integer, Integer> map = new HashMap<>();        int a12 = getDistanceSquare(p1, p2);        int a13 = getDistanceSquare(p1, p3);        int a14 = getDistanceSquare(p1, p4);        int a23 = getDistanceSquare(p2, p3);        int a24 = getDistanceSquare(p2, p4);        int a34 = getDistanceSquare(p3, p4);        if (a12 == 0 || a13 == 0 || a14 == 0 || a23 == 0 || a24 == 0 || a34 == 0){                return false;        }        map.put(a12, map.getOrDefault(a12, 0) + 1);        map.put(a13, map.getOrDefault(a13, 0) + 1);        map.put(a14, map.getOrDefault(a14, 0) + 1);        map.put(a23, map.getOrDefault(a23, 0) + 1);        map.put(a24, map.getOrDefault(a24, 0) + 1);        map.put(a34, map.getOrDefault(a34, 0) + 1);        return map.size() == 2 && (map.get(a12) == 2 || map.get(a12) == 4);    }        private int getDistanceSquare(int[] a, int[] b) {        return (a[0] - b[0]) * (a[0] - b[0]) + (a[1] - b[1]) * (a[1] - b[1]);    }}
这道题有solutions:https://leetcode.com/problems/valid-square/solution/。

Solution


Approach #2 Using Sorting [Accepted]

我们可以不考虑边的所有可能组合情形,而是根据x坐标大小,来对这4个坐标进行排序。如果4个点能构成正方形,且四个坐标按照x坐标从小到大排序为p0,p1,p2,p3,那么构成的正方形只可能是下面3种情况:

Valid_Square

这三种情况下,四条边和斜边都是如下的结论:

  1. p_0p_1p0p1p_1p_3p1p3p_3p_2p3p2 and p_2p_0p2p0 form the four sides of any valid square.

  2. p_0p_3p0p3 and p_1p_2p1p2 form the diagonals of the square.

因此,我们可以比较 p_0p_1p0p1p_1p_3p1p3p_3p_2p3p2 and p_2p_0p2p0 的长度,和 p_0p_3p0p3 and p_1p_2p1p2 的长度。(注意,菱形的话两条斜边是不相等的。)

Java

public class Solution {    public double dist(int[] p1, int[] p2) {        return (p2[1] - p1[1]) * (p2[1] - p1[1]) + (p2[0] - p1[0]) * (p2[0] - p1[0]);    }    public boolean validSquare(int[] p1, int[] p2, int[] p3, int[] p4) {        int[][] p={p1,p2,p3,p4};        Arrays.sort(p, (l1, l2) -> l2[0] == l1[0] ? l1[1] - l2[1] : l1[0] - l2[0]);        return dist(p[0], p[1]) != 0 && dist(p[0], p[1]) == dist(p[1], p[3]) && dist(p[1], p[3]) == dist(p[3], p[2]) && dist(p[3], p[2]) == dist(p[2], p[0])   && dist(p[0],p[3])==dist(p[1],p[2]);    }}

Complexity Analysis

  • Time complexity : O(1)O(1). Sorting 4 points takes constant time.

  • Space complexity : O(1)O(1). Constant space is required.


Approach #3 Checking every case [Accepted]

Algorithm

我们考虑所有组合的可能性(点 按照顺时针排序):

Valid_Square

在图中,相同背景色代表“边集合和斜边集合”相同的情况。我们发现只有3种与众不同的情形。因此,没必要考虑24种情况,只需要看这3种情况。

Java

public class Solution {    public double dist(int[] p1, int[] p2) {        return (p2[1] - p1[1]) * (p2[1] - p1[1]) + (p2[0] - p1[0]) * (p2[0] - p1[0]);    }    public boolean check(int[] p1, int[] p2, int[] p3, int[] p4) {        return dist(p1,p2) > 0 && dist(p1, p2) == dist(p2, p3) && dist(p2, p3) == dist(p3, p4) && dist(p3, p4) == dist(p4, p1) && dist(p1, p3) == dist(p2, p4);    }    public boolean validSquare(int[] p1, int[] p2, int[] p3, int[] p4) {        return check(p1, p2, p3, p4) || check(p1, p3, p2, p4) || check(p1, p2, p4, p3);    }}

Complexity Analysis

  • Time complexity : O(1)O(1). A fixed number of comparisons are done.

  • Space complexity : O(1)O(1). No extra space required.


原创粉丝点击