找出距離最近的三個點

本文章來源於 http://www.jobcoding.com/
問題描述:
給定三個數組A,B,C,從這三個數組中分別取一個元素a,b,c,使得|a-b|+|b-c|+|c-a| 最小。

【方案一】

<直接枚舉法>
該題最直接的方法是枚舉,即枚舉三個數組組成的所有三元組<a,b,c>,然後求出|a-b|+|b-c|+|c-a| 最小值。

【方案二】

<巧妙轉化法>
一般而言,見到絕對值號,首先想到的應是去絕對值號。

枚舉6種a,b,c之間的大小關係,如a>=b>=c,則|a-b|+|b-c|+|c-a| =2(a-c)。
可以得到結論:|a-b|+|b-c|+|c-a|只與a,b,c中最大值和最小值有關。這個很容易通過畫數軸證明,
在數軸上,三個點兩兩距離之和記爲最大值與最小值距離的兩倍。

得到上面結論後,怎樣高效的得到|a-b|+|b-c|+|c-a| 最小值呢?

想一下極端情況:將三個數組合併成一個數組,對該數組排序後,如果相鄰三個數正好來自三個不同數組,
則|a-b|+|b-c|+|c-a| 最小值肯定可通過相鄰三個數獲得。這樣,僅掃描一遍便可求出該最小值。

將該極端情況的算法擴展到一般情況的算法:先對三個數組進行排序,然後用三個指針分別指向三個數組起始位置,
獲取三個指針指向的元素中最大值max和最小值min,計算2(max-min),之後將最小元素對應的指針前移一位,

重複以上過程,保留2(max-min)的最小值即可。

void print_triple_with_min_dist(int *a, int *b, int *c, int n, int m, int s)
{
    sort(a, a + n);
    sort(b, b + m);
    sort(c, c + s);

    int p = 0, q = 0, r = 0, minDis = 1 << 15;

    while(p < n && q < m && r < s)
    {
        int maxP, minP;
        maxP = max(max(a[p], b[q]), c[r]);
        minP = min(min(a[p], b[q]), c[r]);

        minDis = min(minDis, maxP - minP);
        if(a[p] == minP)
            p ++;
        else if(b[q] == minP)
            q ++;
        else
            r ++;
    }
    cout << minDis << endl;
}


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