2018頭條面試演算法方向程式設計題
阿新 • • 發佈:2019-01-29
P為給定的二維平面整數點集。定義 P 中某點x,如果x滿足 P 中任意點都不在 x 的右上方區域內(橫縱座標都大於x),則稱其為“最大的”。求出所有“最大的”點的集合。(所有點的橫座標和縱座標都不重複, 座標軸範圍在[0, 1e9) 內)
如下圖:實心點為滿足條件的點的集合。請實現程式碼找到集合 P 中的所有 ”最大“ 點的集合並輸出。
輸入描述:
第一行輸入點集的個數 N, 接下來 N 行,每行兩個數字代表點的 X 軸和 Y 軸。 對於 50%的資料, 1 <= N <= 10000; 對於 100%的資料, 1 <= N <= 500000;
輸出描述:
輸出“最大的” 點集合, 按照 X 軸從小到大的方式輸出,每行兩個數字分別代表點的 X 軸和 Y軸。
輸入例子1:
5 1 2 5 3 4 6 7 5 9 0
輸出例子1:
4 6 7 5 9 0
題解:
按x軸排序和按y軸排序,標記其id。按x軸從大到小排序,第一個肯定符合,下一個要想符合就要保證上面的y值都小於當前值,因為當前的x值一定比上面的值小,所以如果y值也有比上面小的那這個點肯定不符合,尋找y軸排序的一樣。注意重複的,就用id標記一下
#include <bits/stdc++.h> using namespace std; const int N = 5e5+7; struct node{ int x,y; int id; }a[N],b[N],c[N]; int vis[N]; bool cmp1(node u,node v){ if(u.x!=v.x)return u.x>v.x; return u.y>v.y; } bool cmp2(node u,node v){ if(u.y!=v.y)return u.y>v.y; return u.x>v.x; } int main(){ int n; scanf("%d",&n); memset(vis,0,sizeof(vis)); for(int i = 0;i<n;i++){ scanf("%d%d",&a[i].x,&a[i].y); a[i].id = i; b[i] = a[i]; } sort(a,a+n,cmp1); sort(b,b+n,cmp2); // printf("----------------\n"); // for(int i = 0;i<n;i++){ // printf("%d %d + ",a[i].x,a[i].y); // printf("%d %d\n",b[i].x,b[i].y); // } // printf("----------------\n"); // for(int i = 0;i<n;i++){ // printf("%d %d\n",b[i].x,b[i].y); // } //printf("----------------\n"); int j = 0; int cnt = 0; int my = -1,mx = -1; while(j<n){ if(vis[a[j].id]==0){ vis[a[j].id]=1; if(my>a[j].y)continue; c[cnt++] = a[j]; my = max(my,a[j].y); } j++; } j = 0; while(j<n){ if(vis[a[j].id]==0){ vis[a[j].id]=1; if(mx>a[j].x)continue; c[cnt++] = a[j]; mx = max(mx,a[j].y); } j++; } sort(c,c+cnt,cmp1); for(int i = cnt-1;i>=0;i--){ printf("%d %d\n",c[i].x,c[i].y); } return 0; }