欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++實(shí)現(xiàn)LeetCode(149.共線點(diǎn)個(gè)數(shù))

 更新時(shí)間:2021年07月29日 14:26:52   作者:Grandyang  
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(149.共線點(diǎn)個(gè)數(shù)),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下

[LeetCode] 149. Max Points on a Line 共線點(diǎn)個(gè)數(shù)

Given n points on a 2D plane, find the maximum number of points that lie on the same straight line.

Example 1:

Input: [[1,1],[2,2],[3,3]]
Output: 3
Explanation:
^
|
|        o
|     o
|  o  
+------------->
0  1  2  3  4

Example 2:

Input: [[1,1],[3,2],[5,3],[4,1],[2,3],[1,4]]
Output: 4
Explanation:
^
|
|  o
|     o        o
|        o
|  o        o
+------------------->
0  1  2  3  4  5  6

這道題給了我們一堆二維點(diǎn),然后讓求最大的共線點(diǎn)的個(gè)數(shù),根據(jù)初中數(shù)學(xué)可以知道,兩點(diǎn)確定一條直線,而且可以寫(xiě)成 y = ax + b 的形式,所有共線的點(diǎn)都滿足這個(gè)公式。所以這些給定點(diǎn)兩兩之間都可以算一個(gè)斜率,每個(gè)斜率代表一條直線,對(duì)每一條直線,帶入所有的點(diǎn)看是否共線并計(jì)算個(gè)數(shù),這是整體的思路。但是還有兩點(diǎn)特殊情況需要考慮,一是當(dāng)兩個(gè)點(diǎn)重合時(shí),無(wú)法確定一條直線,但這也是共線的情況,需要特殊處理。二是斜率不存在的情況,由于兩個(gè)點(diǎn) (x1, y1) 和 (x2, y2) 的斜率k表示為 (y2 - y1) / (x2 - x1),那么當(dāng) x1 = x2 時(shí)斜率不存在,這種共線情況需要特殊處理。這里需要用到 TreeMap 來(lái)記錄斜率和共線點(diǎn)個(gè)數(shù)之間的映射,其中第一種重合點(diǎn)的情況假定其斜率為 INT_MIN,第二種情況假定其斜率為 INT_MAX,這樣都可以用 TreeMap 映射了。還需要頂一個(gè)變量 duplicate 來(lái)記錄重合點(diǎn)的個(gè)數(shù),最后只需和 TreeMap 中的數(shù)字相加即為共線點(diǎn)的總數(shù),但這種方法現(xiàn)在已經(jīng)無(wú)法通過(guò) OJ 了,代碼可以參見(jiàn)評(píng)論區(qū)八樓。

由于通過(guò)斜率來(lái)判斷共線需要用到除法,而用 double 表示的雙精度小數(shù)在有的系統(tǒng)里不一定準(zhǔn)確,為了更加精確無(wú)誤的計(jì)算共線,應(yīng)當(dāng)避免除法,從而避免無(wú)線不循環(huán)小數(shù)的出現(xiàn),那么怎么辦呢,這里把除數(shù)和被除數(shù)都保存下來(lái),不做除法,但是要讓這兩數(shù)分別除以它們的最大公約數(shù),這樣例如8和4,4和2,2和1,這三組商相同的數(shù)就都會(huì)存到一個(gè)映射里面,同樣也能實(shí)現(xiàn)目標(biāo),而求 GCD 的函數(shù)如果用遞歸來(lái)寫(xiě)那么一行就搞定了,叼不叼,這個(gè)方法能很好的避免除法的出現(xiàn),算是犧牲了空間來(lái)保證精度吧,參見(jiàn)代碼如下:

C++ 解法一:

class Solution {
public:
    int maxPoints(vector<vector<int>>& points) {
        int res = 0;
        for (int i = 0; i < points.size(); ++i) {
            map<pair<int, int>, int> m;
            int duplicate = 1;
            for (int j = i + 1; j < points.size(); ++j) {
                if (points[i][0] == points[j][0] && points[i][1] == points[j][1]) {
                    ++duplicate; continue;
                } 
                int dx = points[j][0] - points[i][0];
                int dy = points[j][1] - points[i][1];
                int d = gcd(dx, dy);
                ++m[{dx / d, dy / d}];
            }
            res = max(res, duplicate);
            for (auto it = m.begin(); it != m.end(); ++it) {
                res = max(res, it->second + duplicate);
            }
        }
        return res;
    }
    int gcd(int a, int b) {
        return (b == 0) ? a : gcd(b, a % b);
    }
};

Java 解法一:

class Solution {
    public int maxPoints(int[][] points) {
        int res = 0;
        for (int i = 0; i < points.length; ++i) {
            Map<Map<Integer, Integer>, Integer> m = new HashMap<>();
            int duplicate = 1;
            for (int j = i + 1; j < points.length; ++j) {
                if (points[i][0] == points[j][0] && points[i][1] == points[j][1]) {
                    ++duplicate; continue;
                }
                int dx = points[j][0] - points[i][0];
                int dy = points[j][1] - points[i][1];
                int d = gcd(dx, dy);
                Map<Integer, Integer> t = new HashMap<>();
                t.put(dx / d, dy / d);
                m.put(t, m.getOrDefault(t, 0) + 1);
            }
            res = Math.max(res, duplicate);
            for (Map.Entry<Map<Integer, Integer>, Integer> e : m.entrySet()) {
                res = Math.max(res, e.getValue() + duplicate);
            }
        }
        return res;
    }
    public int gcd(int a, int b) {
        return (b == 0) ? a : gcd(b, a % b);
    }
}

令博主驚奇的是,這道題的 OJ 居然容忍 brute force 的方法通過(guò),博主認(rèn)為下面這種 O(n3) 的解法之所以能通過(guò) OJ,可能還有一個(gè)原因就是用了比較高效的判斷三點(diǎn)共線的方法。一般來(lái)說(shuō)判斷三點(diǎn)共線有三種方法,斜率法,周長(zhǎng)法,面積法 。而其中通過(guò)判斷叉積為零的面積法是墜好的。比如說(shuō)有三個(gè)點(diǎn) A(x1, y1)、B(x2, y2)、C(x3, y3),那么判斷三點(diǎn)共線就是判斷下面這個(gè)等式是否成立:

行列式的求法不用多說(shuō)吧,不會(huì)的話回去翻線性代數(shù),當(dāng)初少打點(diǎn)刀塔不就好啦~

C++ 解法二:

class Solution {
public:
    int maxPoints(vector<vector<int>>& points) {
        int res = 0;
        for (int i = 0; i < points.size(); ++i) {
            int duplicate = 1;
            for (int j = i + 1; j < points.size(); ++j) {
                int cnt = 0;
                long long x1 = points[i][0], y1 = points[i][1];
                long long x2 = points[j][0], y2 = points[j][1];
                if (x1 == x2 && y1 == y2) {++duplicate; continue;}
                for (int k = 0; k < points.size(); ++k) {
                    int x3 = points[k][0], y3 = points[k][1];
                    if (x1 * y2 + x2 * y3 + x3 * y1 - x3 * y2 - x2 * y1 - x1 * y3 == 0) {
                        ++cnt;
                    }
                }
                res = max(res, cnt);
            }
            res = max(res, duplicate);
        }
        return res;
    }
};

Java 解法二:

class Solution {
    public int maxPoints(int[][] points) {
        int res = 0, n = points.length;
        for (int i = 0; i < n; ++i) {
            int duplicate = 1;
            for (int j = i + 1; j < n; ++j) {
                int cnt = 0;
                long x1 = points[i][0], y1 = points[i][1];
                long x2 = points[j][0], y2 = points[j][1];
                if (x1 == x2 && y1 == y2) {++duplicate;continue;}
                for (int k = 0; k < n; ++k) {
                    int x3 = points[k][0], y3 = points[k][1];
                    if (x1*y2 + x2*y3 + x3*y1 - x3*y2 - x2*y1 - x1 * y3 == 0) {
                        ++cnt;
                    }
                }
                res = Math.max(res, cnt);
            }
            res = Math.max(res, duplicate);
        }
        return res;
    }
}

Github 同步地址:

https://github.com/grandyang/leetcode/issues/149

類(lèi)似題目:

Line Reflection

參考資料:

https://leetcode.com/problems/max-points-on-a-line/

https://leetcode.com/problems/max-points-on-a-line/discuss/221044/

https://leetcode.com/problems/max-points-on-a-line/discuss/47113/A-java-solution-with-notes

https://leetcode.com/problems/max-points-on-a-line/discuss/47117/Sharing-my-simple-solution-with-explanation

到此這篇關(guān)于C++實(shí)現(xiàn)LeetCode(149.共線點(diǎn)個(gè)數(shù))的文章就介紹到這了,更多相關(guān)C++實(shí)現(xiàn)共線點(diǎn)個(gè)數(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 虛函數(shù)與純虛函數(shù)(C++與Java虛函數(shù)的區(qū)別)的深入分析

    虛函數(shù)與純虛函數(shù)(C++與Java虛函數(shù)的區(qū)別)的深入分析

    本篇文章是對(duì)虛函數(shù)與純虛函數(shù)進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-06-06
  • 詳解C++中vector的理解以及模擬實(shí)現(xiàn)

    詳解C++中vector的理解以及模擬實(shí)現(xiàn)

    vector是表示可變大小數(shù)組的序列容器。這篇文章主要為大家詳細(xì)介紹了vector的理解以及模擬實(shí)現(xiàn),文中的示例代碼講解詳細(xì),感興趣的可以了解一下
    2023-03-03
  • C++程序代碼優(yōu)化的方法實(shí)例大全

    C++程序代碼優(yōu)化的方法實(shí)例大全

    優(yōu)化是一個(gè)非常大的主題,本文并不是去深入探討性能分析理論,算法的效率,這篇文章主要給大家介紹了關(guān)于C++代碼優(yōu)化的相關(guān)資料,需要的朋友可以參考下
    2022-03-03
  • C++二分查找(折半查找)算法實(shí)例詳解

    C++二分查找(折半查找)算法實(shí)例詳解

    這篇文章主要介紹了C++二分查找(折半查找)算法,結(jié)合實(shí)例形式詳細(xì)分析了二分查找算法的原理、思想、實(shí)現(xiàn)方法與相關(guān)操作技巧,需要的朋友可以參考下
    2017-05-05
  • 在C++程序中開(kāi)啟和禁用Windows設(shè)備的無(wú)線網(wǎng)卡的方法

    在C++程序中開(kāi)啟和禁用Windows設(shè)備的無(wú)線網(wǎng)卡的方法

    這篇文章主要介紹了在C++程序中開(kāi)啟和禁用Windows設(shè)備的無(wú)線網(wǎng)卡的方法,包括一些常見(jiàn)錯(cuò)誤的分析與解決,需要的朋友可以參考下
    2016-03-03
  • c語(yǔ)言動(dòng)態(tài)數(shù)組示例

    c語(yǔ)言動(dòng)態(tài)數(shù)組示例

    這是一個(gè)簡(jiǎn)單的動(dòng)態(tài)分配數(shù)組大小的例子,需要的朋友可以參考下
    2014-04-04
  • C++?雙向循環(huán)鏈表類(lèi)模版實(shí)例詳解

    C++?雙向循環(huán)鏈表類(lèi)模版實(shí)例詳解

    這篇文章主要為大家詳細(xì)介紹了C++?雙向循環(huán)鏈表類(lèi)模版實(shí)例,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-02-02
  • C語(yǔ)言俄羅斯方塊游戲課程設(shè)計(jì)

    C語(yǔ)言俄羅斯方塊游戲課程設(shè)計(jì)

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言俄羅斯方塊游戲課程設(shè)計(jì),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-06-06
  • C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)之復(fù)雜鏈表的拷貝

    C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)之復(fù)雜鏈表的拷貝

    復(fù)雜鏈表指的是一個(gè)鏈表有若干個(gè)結(jié)點(diǎn),每個(gè)結(jié)點(diǎn)有一個(gè)數(shù)據(jù)域用于存放數(shù)據(jù),還有兩個(gè)指針域,其中一個(gè)指向下一個(gè)節(jié)點(diǎn),還有一個(gè)隨機(jī)指向當(dāng)前復(fù)雜鏈表中的任意一個(gè)節(jié)點(diǎn)或者是一個(gè)空結(jié)點(diǎn)。今天我們要實(shí)現(xiàn)的就是對(duì)這樣一個(gè)復(fù)雜鏈表復(fù)制產(chǎn)生一個(gè)新的復(fù)雜鏈表
    2021-11-11
  • C語(yǔ)言形參和實(shí)參傳值和傳址詳解刨析

    C語(yǔ)言形參和實(shí)參傳值和傳址詳解刨析

    形參出現(xiàn)在函數(shù)定義中,在整個(gè)函數(shù)體內(nèi)都可以使用, 離開(kāi)該函數(shù)則不能使用。實(shí)參出現(xiàn)在主調(diào)函數(shù)中,進(jìn)入被調(diào)函數(shù)后,實(shí)參變量也不能使用,形參和實(shí)參的功能是作數(shù)據(jù)傳送。發(fā)生函數(shù)調(diào)用時(shí), 主調(diào)函數(shù)把實(shí)參的值傳送給被調(diào)函數(shù)的形參從而實(shí)現(xiàn)主調(diào)函數(shù)向被調(diào)函數(shù)的數(shù)據(jù)傳送
    2021-11-11

最新評(píng)論