求找出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问题,是否可以转换为树的大顶锥问题;

猜你喜欢

转载自blog.csdn.net/fct2001140269/article/details/85098176