今日头条机试题

描述:具体的文字已经没法还原,大概意思是:二维坐标里有N个点,从任意一点出发,只能向上向下向左向右四个方向走,碰到其他点才可以改变方向,请问至少要补充多少点可以跑遍所有点。

分析:图的遍历!!当时机试时没想到,脑子短路了!直接上代码!尴尬

 

 

package shangjiceshi.jinritoutiao;

import java.util.*;

//9:35起做题, 10:40结束,仅仅是编码,思考和测试的时间没有算入!!!!一个半小时最多做一道题!!!后来又花了一些时间修改了几个关键点,之前漏掉了,表示绝望!!!
//现在想想不难,其实就是图的遍历,但是实现起来非常复杂!!!!


public class JinRiTouTiaoTest2 {

	public static void main(String[] args) {
		@SuppressWarnings("resource")
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		HashMap<String, Point> points = new HashMap<>();
		for(int i = 0; i < n; i++) {
			int x = sc.nextInt();
			int y = sc.nextInt();
			String key = x + "_" + y;
			points.put(key, new Point(x,y,key));
		}
		solve(points);
	}
	
	private static void solve(HashMap<String, Point> points) {
		HashMap<String, Boolean> isTo = new HashMap<>();  //标记是否经历过该点,key为点的key
		for(String key: points.keySet()) {
			isTo.put(key, false);
		}
		int num = 0; //外层遍历的次数
		HashMap<Integer, HashSet<Point> > xMap = constructXMap(points);
		HashMap<Integer, HashSet<Point> > yMap = constructYMap(points);
		for(String key: isTo.keySet()) {
			if(isTo.get(key) == true) {
				continue;
			}
			num++;
			traverse(points, isTo, xMap, yMap, points.get(key));  //内层遍历
		}
		System.out.println(num-1);
	}

	private static HashMap<Integer, HashSet<Point>> constructXMap(HashMap<String, Point> points) {
		HashMap<Integer, HashSet<Point>> result = new HashMap<>();
		for(Point value: points.values()) {
			int x = value.x;
			HashSet<Point> set = null;
			if(!result.containsKey(x)) {
				set = new HashSet<>();
				result.put(x, set);
			} else {
				set = result.get(x);
			}
			set.add(value);
		}
		return result;
	}

	private static HashMap<Integer, HashSet<Point>> constructYMap(HashMap<String, Point> points) {
		HashMap<Integer, HashSet<Point>> result = new HashMap<>();
		for(Point value: points.values()) {
			int y = value.y;
			HashSet<Point> set = null;
			if(!result.containsKey(y)) {
				set = new HashSet<>();
				result.put(y, set);
			} else {
				set = result.get(y);
			}
			set.add(value);
		}
		return result;
	}
	
	private static void traverse(HashMap<String, Point> points, HashMap<String, Boolean> isTo,
			HashMap<Integer, HashSet<Point>> xMap, HashMap<Integer, HashSet<Point>> yMap, Point point) {
		//这几个参数都是非常重要的数据结构!!!!能快速拿到想要的数据!!!!
		HashSet<Integer> xset = new HashSet<>();   //已经到达的x坐标的集合,内部遍历很重要的数据结构
		HashSet<Integer> yset = new HashSet<>();   //已经到达的y坐标的集合,内部遍历很重要的数据结构
		LinkedList<Point> list = new LinkedList<>(); //尚未遍历的点,包括一些已经遍历过的,重复没关系,会有一种机制会去除
		list.add(point);
		while(!list.isEmpty()) {
			Point p = list.removeFirst();
			if(isTo.get(p.key) == true) {    //开始漏掉了,这个地方很重要!!!!否则非常耗性能!!
				continue;
			}
			isTo.put(p.key, true);    //标记已经经过,很重要!内部遍历重复没关系
			if(!xset.contains(p.x)) {
				list.addAll(xMap.get(p.x));    //加入了一些遍历过的点,所有没遍历的点也在其中
				xset.add(p.x);     //这个地方开始也漏掉了。。。。。。也是很伤!!!!!
			}
			if(!yset.contains(p.y)) {    
				list.addAll(yMap.get(p.y));   //同上
				yset.add(p.y);                //同上
			}
		}
	}
	
	public static class Point {
		int x;
		int y;
		String key;  //key由x_y组成
		public Point(int x, int y, String key) {
			this.x = x;
			this.y = y;
			this.key = key;
		}
	}
}

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值