题目
https://www.lintcode.com/problem/1832
java
有一个1∗n的棋盘,分别标号为0,1,2..n−1,棋盘的每个格子都有一种颜色。
现在,在0号位置有一枚棋子,请求出最少移动几步能到达最后一格。
棋子有3种移动的方法,且棋子不能移出到棋盘外:
棋子从位置 i 移动到位置 i+1。
棋子从位置 i 移动到位置 i−1。
如果位置 i 和位置 j 的颜色相同,那么棋子可以直接从位置 i 移动到位置 j。
棋盘的大小为 1∗n,2≤n≤10 ^5 。
第 i 格子的颜色编号 colors i ,满足 1≤colors i ≤n。
样例
样例 1
输入:
colors = [1, 2, 3, 3, 2, 5]
输出:
3
解释:
在样例中,棋子最少用 3 步走到最后的位置:
1. 从位置 0 走到位置 1。
2. 由于位置 1 和位置 4 的颜色相同,从位置 1 走到位置 4。
3. 从位置 4 走到位置 5。
前置知识
宽度优先遍历BFS
代码
java
public class Solution {
/**
* @param colors: the colors of grids
* @return: return the minimum step from position 0 to position n - 1
*/
public int minimumStep(List<Integer> colors) {
//colors = [1, 2, 3, 3, 2, 5]
// BFS
Map<Integer,List<Integer>> sameColor = new HashMap<>(); //k:颜色 v:位置列表
int n= colors.size();
for (int i = 0; i <n; i++) {
int c = colors.get(i);
if(!sameColor.containsKey(c))
sameColor.put(c,new ArrayList<>());
sameColor.get(c).add(i);
}
boolean[] visited = new boolean[n];
Queue<Integer> q = new LinkedList<>(); //q 存放位置下标
q.add(0); //从0开始
visited[0]= true;
int steps =0;
while (!q.isEmpty()){
int size = q.size();
boolean arriveEnd= false;
for (int i = 0; i <size ; i++) {
int cur= q.poll();
if(cur == n-1) {
arriveEnd = true;
break;
}
List<Integer> nexts = getNexts(cur,colors,sameColor,visited);
for (Integer next : nexts) {
visited[next] =true;
q.add(next);
}
// cur对应的颜色都走过了,将其在哈希表里删除
sameColor.remove(colors.get(cur)); //本题要通过,这里是关键
}
if(arriveEnd) break;
steps++; //走了一步了
}
return steps;
}
//到cur位置时再获取该位置可以跳的位置
public static List<Integer> getNexts(int cur,List<Integer> colors,Map<Integer,List<Integer>> sameColor,boolean[] visited){
List<Integer> nexts = new ArrayList<>();
int n= colors.size();
// 向右走
if (cur<= n -2 && !visited[cur + 1]) {
nexts.add(cur + 1);
}
// 如果走到n - 1的位置了,直接返回
if (nexts.contains(n - 1)) {
return nexts;
}
// 向左走
if (cur >= 1 && !visited[cur - 1]) {
nexts.add(cur - 1);
}
//向相同的颜色走
int c = colors.get(cur);
if(sameColor.containsKey(c)){
for (Integer next : sameColor.get(c)) {
if(next ==n-1){
return Arrays.asList(n-1);
}
if(!visited[next])
nexts.add(next);
}
}
return nexts;
}
}