描述:具体的文字已经没法还原,大概意思是:二维坐标里有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;
}
}
}