lintcode 1832 · 最小步数【BFS 中等】

题目

https://www.lintcode.com/problem/1832

有一个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 走到位置 12. 由于位置 1 和位置 4 的颜色相同,从位置 1 走到位置 43. 从位置 4 走到位置 5

前置知识

宽度优先遍历BFS

代码

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;
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_37991016/article/details/132817251