1. 程式人生 > >求找出N個格子中前m個的最多人走過的格子??

求找出N個格子中前m個的最多人走過的格子??

題目
對於一個區域中N個地理格子,給定很多人走過的軌跡,求找出N個格子中前m個最多人走過的格子??

實現

package grid.geo;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.
TreeMap; import java.util.TreeSet; import java.util.Map.Entry; import cetc.ocean.common.geohash.GeoHash; /** * 描述:對於一個區域中N個地理格子,給定很多人走過的軌跡orignGrid ,求找出N個格子中前m個最多人走過的格子?? * @author: fangchangtan * @version 建立時間:2018年12月19日 下午1:56:24 */ public class GridCountTop { //orignGrid 表示原始N個格子,此處使用geohash代替
String orignGrid ="geohash1,geohash2,...."; //初始化讀取orignGrid 格子到快取中 static HashSet<String> setInitGridNum = new HashSet<>(); //歷史軌跡點,存入有序集合中 ArrayList<TrackPointBean> trackHistory = new ArrayList<>(); //mapTrackPoints 表示輔助快取:HashSet自動過濾掉重複的人 Map<String, HashSet<Integer>
> mapTrackPoints = new HashMap<>(); public static void main(String[] args) { GridCountTop gridCountTop = new GridCountTop(); gridCountTop.initGrid(); List<String> gridTopN = gridCountTop.getGridTopN(5); for (String geohash : gridTopN) { System.out.println("N個格子中前m個最多人走過的格子geohash為:"+geohash); } } /*讀取初始N個格子 */ public void initGrid() { String[] split = orignGrid.split(","); for (String grid : split) { setInitGridNum.add(grid); } System.out.println("orign grid num:"+setInitGridNum.size()); //初始化軌跡快取trackHistory //........ } /*topN 表示:前m個格子 */ public List<String> getGridTopN(int topN ) { for (TrackPointBean trackPointBean : trackHistory) { int userId = trackPointBean.getUserId(); String curr_geohash5 = GeoHash.geoHashStringWithCharacterPrecision(trackPointBean.getLat(), trackPointBean.getLon(), 5); if (setInitGridNum.contains(curr_geohash5)) { if (mapTrackPoints.containsKey(curr_geohash5)) { mapTrackPoints.get(curr_geohash5).add(userId); }else { mapTrackPoints.put(curr_geohash5,new HashSet<Integer>(){{add(userId);}}); } } } TreeSet<KeyBean> treeSet = new TreeSet<>(); for (Entry<String, HashSet<Integer>> entry : mapTrackPoints.entrySet()) { int size = entry.getValue().size(); String geohash5 = entry.getKey(); KeyBean keyBean = new KeyBean(size, geohash5); treeSet.add(keyBean); } ArrayList<String> arrayList = new ArrayList<>(); if (treeSet.size() > topN) { Iterator<KeyBean> iterator = treeSet.iterator(); for (int i = 0; i < topN; i++) { arrayList.add(iterator.next().getGeohash()); } }else { Iterator<KeyBean> iterator = treeSet.iterator(); while (iterator.hasNext()) { arrayList.add(iterator.next().getGeohash()); } } return arrayList; } /*自定義從大到小的類比較器 */ class KeyBean implements Comparator<KeyBean> { int num; String geohash; public KeyBean(int num, String geohash) { super(); this.num = num; this.geohash = geohash; } public int getNum() { return num; } public void setNum(int num) { this.num = num; } public String getGeohash() { return geohash; } public void setGeohash(String geohash) { this.geohash = geohash; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + getOuterType().hashCode(); result = prime * result + ((geohash == null) ? 0 : geohash.hashCode()); result = prime * result + num; return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; KeyBean other = (KeyBean) obj; if (!getOuterType().equals(other.getOuterType())) return false; if (geohash == null) { if (other.geohash != null) return false; } else if (!geohash.equals(other.geohash)) return false; if (num != other.num) return false; return true; } //逆序輸出 @Override public int compare(KeyBean o1, KeyBean o2) { // TODO Auto-generated method stub if (o1.getNum() != o2.getNum()) { return o2.getNum()-o1.getNum(); }else { return o2.getGeohash().compareTo(o1.getGeohash()); } } } /*自定義軌跡點 */ class TrackPointBean { private int userId; private double lon; private double lat; private double utc; public TrackPointBean(int userId, double lon, double lat, double utc) { super(); this.userId = userId; this.lon = lon; this.lat = lat; this.utc = utc; } public int getUserId() { return userId; } public void setUserId(int userId) { this.userId = userId; } public double getLon() { return lon; } public void setLon(double lon) { this.lon = lon; } public double getLat() { return lat; } public void setLat(double lat) { this.lat = lat; } public double getUtc() { return utc; } public void setUtc(double utc) { this.utc = utc; } @Override public String toString() { return "TrackPointBean [userId=" + userId + ", lon=" + lon + ", lat=" + lat + ", utc=" + utc + "]"; } } }

寫完程式碼我們看一下程式碼的演算法複雜度
第一步:遍歷所有的軌跡點(數量為P),存入mapTrackPoints中;
第二步:遍歷mapTrackPoints的結果中value和key反向解析組合成KeyBean後存入TreeSet(大小為Q)中(倒敘輸出);這時候直接取出前N個至就行了;
演算法複雜度為P+Q+N;

存在的問題:
1.沒有考慮相鄰軌跡點同是跨過N個格子的問題;比如從第1格直接跳到第3個格子的問題;
2.這種依靠java中集合來實現的功能並不是最有的,前N問題,是否可以轉換為樹的大頂錐問題;