LeetCode 面試題16.03 交點

又是暴力破解的一天

而且還是個數學渣

剛看到這一題的時候真的崩潰,稍微列了一下公式後好一點,但又發現按這種解法情況太多

但是自己分的情況跪着也要分完

 

下面先列一下思路:我採用的是最普通的點斜式方程

  • 計算兩根直線斜率,判斷兩根線段的斜率是否存在

    • 都存在
      • 判斷是否平行
        • 平行但不重合
          • 此時一定沒有交點,返回空數組
        • 重合
          • 判斷哪一部分重合並返回題目中所要求的最小點
        • 不平行
          • 計算出兩根直線的點斜式方程
          • 計算兩根直線交點,並判斷交點是否在兩根線段範圍內
    • 有一根不存在(垂直於x軸)
      • 直線一定重合,但線段不一定重合
      • 計算斜率存在那根直線的點斜式方程
      • 計算直線交點,並判斷交點是否在兩根線段範圍內
    • 兩根都不存在(兩根都垂直於x軸)
      • 只可能平行或者重合
      • 判斷是否重合
        • 重合,則判斷哪一部分重合並返回題目中所要求的最小點
        • 平行,返回空數組

 

下面是在提交過程中修改了很多次的代碼...

代碼能力是挺差勁的,就看看思路吧(也沒啥好看的

提交時修改的幾個點:

1. 計算k(斜率)時,要先強轉成double,否則int類型會出錯

2. double類型是存在infinity類型的,所以要判斷,直接是拋不出異常的

3. 判斷交點是否在線段內時不要忘記等號

最後結果是(我盡力了):

執行用時 :8 ms, 在所有 Java 提交中擊敗了18.52%的用戶

內存消耗 :39 MB, 在所有 Java 提交中擊敗了100.00%的用戶

public static double[] intersection(int[] start1, int[] end1, int[] start2, int[] end2) {
	    //計算k1 k2
		double x_res = 0;
		double y_res = 0;
		
		try {
			//k1 k2均存在
			double k1 = (double)(end1[1] - start1[1])/(double)(end1[0] - start1[0]);
			if(k1 == Double.POSITIVE_INFINITY || k1 == Double.NEGATIVE_INFINITY) {
				throw new Exception();
			}
			double b1 = start1[1] - k1*start1[0];
			
			double k2 = (double)(end2[1] - start2[1])/(double)(end2[0] - start2[0]);
			double b2 = start2[1] - k2*start2[0];
			
			if(k1 == k2 && b1==b2) { //重合但不一定相交
				if(Math.min(start2[0],end2[0]) >= Math.min(start1[0], end1[0]) && Math.min(start2[0],end2[0]) <= Math.max(start1[0], end1[0])) {
					return new double[] {Math.min(start2[0],end2[0]), Math.min(start2[0],end2[0])*k1+b1};
				} else if(Math.max(start2[0],end2[0]) >= Math.min(start1[0], end1[0]) && Math.max(start2[0],end2[0]) <= Math.max(start1[0], end1[0])) {
					return new double[] {Math.min(start1[0],end1[0]), Math.min(start1[0],end1[0])*k1+b1};
				} else {
					return new double[] {};
				}
			}
			else if (k1 == k2 && b1 != b2) //平行
			{
				return new double[] {};
			} else { //既不平行也不重合
				x_res = (b1-b2)/(k2-k1);
				y_res = k1*x_res + b1;
				System.out.println(x_res + " " + y_res);
				if(x_res >= Math.min(start1[0], end1[0]) && x_res <= Math.max(start1[0], end1[0]) && y_res <= Math.max(start2[1], end2[1]) && y_res >= Math.min(start2[1], end2[1])) { //有交點
					return new double[] {x_res, y_res};
				} else {
					return new double[] {};
				}
				
			}
			
		} catch (Exception e) { //k1爲無窮大 第一條線段爲x=start1[0]
//			System.out.println("k1true");
			x_res = start1[0];
			
			try { //可能有交點
				double k2 = (double)(end2[1] - start2[1])/(double)(end2[0] - start2[0]);
				if(k2 == Double.POSITIVE_INFINITY || k2 == Double.NEGATIVE_INFINITY) {
					throw new Exception();
				}
				
				double b2 = start2[1] - k2*start2[0];

				if(x_res >= Math.min(start1[0], end1[0]) && x_res <= Math.max(start1[0], end1[0])) { //有交點
					y_res = k2*x_res + b2;
					return new double[] {x_res, y_res};
				} else { //無交點
					return new double[] {};
				}
				
			} catch (Exception e2) { //兩條線段都垂直於x軸
				if(x_res == start2[0]) { //重合
//					System.out.println(true);
//					System.out.println(Math.min(start2[1],end2[1]));
					if(Math.min(start2[1],end2[1]) >= Math.min(start1[1], end1[1]) && Math.min(start2[1],end2[1]) <= Math.max(start1[1], end1[1])) {
						return new double[] {x_res, Math.min(start2[1],end2[1])};
					} else if(Math.max(start2[1],end2[1]) >= Math.min(start1[1], end1[1]) && Math.max(start2[1],end2[1]) <= Math.max(start1[1], end1[1])) {
						return new double[] {x_res, Math.min(start1[1],end1[1])};
					} else {
						return new double[] {};
					}
				} else { //沒有交點
					return new double[] {};
				}
			}
		}
	
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章