标签:
rank finding 问题的概述如下:
在一群离散的点中,检查对于每个点,是否有x值和y值都小于它的点,若有,则该点的秩为这些小于它的点的数量。
分治法思想:
以界面上所有点中x值的中位数为基准,递归地把目标区域分成两部分,直到每个区域中的点在一个以下,对于每一个细小的区域,检查其left child区域中的点的y值和right child区域中的点的y值,以对right child中的点的秩进行统计。
该方法通过分治排除了水平位置不符合标准的点,有效的减少了统计次数。
代码示例如下:
#include <algorithm> #include <iostream> #include <vector> #include <cstring> const int MAX_N = 1000; struct Point { int x; int y; }; bool cmpx(Point a, Point b) { return a.x < b.x; } bool cmpy(Point a, Point b) { return a.y < b.y; } int rank[MAX_N][MAX_N]; Point S[MAX_N]; //点集,起始点,终点+1 void rankFinding(Point S[], int from, int to) { int n = to - from; if (n <= 0) { return; } if (n == 1) { rank[S[from].x][S[from].y] = 0; return; } std::sort(S + from, S + to, cmpx);//n*log(n) int l = (to + from) / 2; rankFinding(S, from, l);//2*T(n/2) rankFinding(S, l, to); std::sort(S + from, S + l, cmpy);//2*(n/2)*log(n/2) std::sort(S + l, S + to, cmpy); for (int i = l; i < to; ++i) { for (int j = from; j < l; ++j) { if (S[i].y > S[j].y) { rank[S[i].x][S[i].y]++; } } } } int main() { memset(rank, -1, sizeof(rank)); memset(S, 0, sizeof(S)); S[0] = { 1, 1 }; S[1] = { 1, 3 }; S[2] = { 2, 5 }; S[3] = { 6, 2 }; S[4] = { 9, 3 }; S[5] = { 4, 8 }; S[6] = { 7, 6 }; S[7] = { 5, 5 }; S[8] = { 2, 3 }; rankFinding(S, 0, 9); for (int i = 0; i < MAX_N; ++i) { for (int j = 0; j < MAX_N; ++j) { if (rank[i][j] != -1) { std::cout << i << ‘ ‘ << j << ‘ ‘ << rank[i][j] << std::endl; } } } }
由代码中标记,复杂度
T(n)=2*T(n/2)+n*log(n)+2*(n/2)*(log(n/2))
=2*T(n/2)+n*(2*log(n)-1)=2*(T(n/2)+n*log(n)-n)
T(2^k)=2*(T(2^(k-1))+(k-1)*(2^k)))=2^(k-1)*(T(1))+(2^k)*(k-1)^2=(2^k)*(T(1)/2+(k-1)^2)
T(n)=n*(T(1)/2+(log(n))^2)
所以复杂度为O(n*(log(n))^2)
基于分治法的找秩(maxium rank finding)策略
标签:
原文地址:http://www.cnblogs.com/cielosun/p/5654575.html