天天看点

寻找最近点对 编程之美2.11

2016年搜狗笔试出现微软编程之美2.11寻找最近点对题目。编程之美上面已经说的很清楚了,使用蛮力法时间复杂度为O(n*n),使用分治递归时间复杂度为O(n*log n)。以下是代码实现:

#include<vector>

#include<iostream>

#include<utility>

#include<regex>

using namespace std;

typedef tuple<double, double,int> dpoint;         //x,y,inoutIndex

typedef tuple<double, dpoint, dpoint>answerType;//distance,point1,point2

void inputPointData(vector<dpoint> &inArray)    //input

{

    int N;

    dpoint buf;

    cin >> N;

    inArray.reserve(N);

    while (N--)

    {

        cin >> get<0>(buf) >> get<1>(buf);

        get<2>(buf) = N;

        inArray.push_back(buf);

    }

}

inline answerType get2PointDistance(dpoint &p1, dpoint &p2)

{

    return make_tuple(sqrt((get<0>(p1) - get<0>(p2))*(get<0>(p1) - get<0>(p2))

        + (get<1>(p1) - get<1>(p2))*(get<1>(p1) - get<1>(p2)))

        , p1, p2);

}

answerType GetMinDistance(vector<dpoint> &inArray, int minIndex, int maxIndex)

{

    if (maxIndex - minIndex == 1)

        return get2PointDistance(inArray[minIndex], inArray[maxIndex]);

    else    if (maxIndex - minIndex == 2)

    {

        answerType buf[3];

        buf[0] = get2PointDistance(inArray[minIndex], inArray[maxIndex]);

        buf[1] =get2PointDistance(inArray[minIndex], inArray[maxIndex-1]);

        buf[2] = get2PointDistance(inArray[minIndex+1], inArray[maxIndex]);    

        if (get<0>(buf[0]) < get<0>(buf[1]))

        {

            if (get<0>(buf[0]) < get<0>(buf[2])) return buf[0];

        }

         else if (get<0>(buf[1])< get<0>(buf[2])) return buf[1];

         return buf[2];

    }

    else if (maxIndex <=minIndex)

        return make_tuple(numeric_limits<double>::max(), inArray[minIndex], inArray[maxIndex]);

    int halfIndex = (minIndex + maxIndex) / 2;

    auto lowAns = GetMinDistance(inArray, minIndex, halfIndex);

    auto highAns = GetMinDistance(inArray, halfIndex + 1, maxIndex);

    auto minDis = get<0>(lowAns) < get<0>(highAns) ? lowAns : highAns;

    int bufIndexLow = halfIndex - 1, bufIndexHigh = halfIndex+1;

    while ( bufIndexLow >= 0&&(get<0>(inArray[bufIndexLow]) >= get<0>(minDis) +get<0>(inArray[halfIndex])))--bufIndexLow;

    while (bufIndexHigh<inArray.size()&&get<0>(inArray[bufIndexHigh]) <= get<0>(minDis) +get<0>(inArray[halfIndex]))++bufIndexHigh;

    if (bufIndexHigh - bufIndexLow + 2>0)

    {

        auto  thisAns = GetMinDistance(inArray, bufIndexLow + 1, bufIndexHigh - 1);

        return get<0>(minDis) < get<0>(thisAns) ? minDis : thisAns;

    }

    else return minDis;

}

//分治

int main()

{

    vector<dpoint> pointArray;

    inputPointData(pointArray); //input

    sort(pointArray.begin(), pointArray.end(), [](dpoint &d1, dpoint &d2){ return get<0>(d1) < get<0>(d2) ? true : false; }); //sort by x

    auto answer=GetMinDistance(pointArray, 0, pointArray.size()-1);

    auto p1 = get<1>(answer);

    auto p2 = get<2>(answer);

    if (get<2>(p1)<get<2>(p2))

        cout << get<2>(p1)<<' '<<get<2>(p2);

    else

        cout << get<2>(p2) << ' ' << get<2>(p1);

    return 0;

}

继续阅读