【Lintcode】1832. Minimum Step

题目地址:

https://www.lintcode.com/problem/minimum-step/description

给定一个长 n n n的数组 A A A,每个位置编号 0 ∼ n − 1 0\sim n-1 0n1 A [ i ] A[i] A[i]代表下标 i i i这个位置的颜色。从下标 0 0 0开始出发,每次可以向左或右移动一步,或者走到相同颜色的任意位置。问至少多少次能走到下标 n − 1 n-1 n1的位置。

思路是BFS。注意,如果某个颜色已经走过,下次再走到这个颜色的时候可以直接略过,因为第二次走到之前走过的颜色所得的路径一定不会更短。这样可以节省时间。代码如下:

import java.util.*;

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) {
        // write your code here
        if (colors.isEmpty() || colors.size() == 1) {
            return 0;
        }
        
        // 统计一下每个颜色在哪些位置出现过
        Map<Integer, List<Integer>> map = new HashMap<>();
        for (int i = 0; i < colors.size(); i++) {
            int color = colors.get(i);
            map.putIfAbsent(color, new ArrayList<>());
            map.get(color).add(i);
        }
        
        int res = 0;
        boolean[] visited = new boolean[colors.size()];
        visited[0] = true;
        
        Queue<Integer> queue = new LinkedList<>();
        queue.offer(0);
        
        while (!queue.isEmpty()) {
            res++;
            // 要分层,所以记录size
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                int cur = queue.poll();
                for (int next : getNexts(cur, colors, map, visited)) {
                	// 如果走到了n - 1的位置,则返回步数
                    if (next == colors.size() - 1) {
                        return res;
                    }
                    
                    visited[next] = true;
                    queue.offer(next);
                }
                
                // cur对应的颜色都走过了,将其在哈希表里删除
                map.remove(colors.get(cur));
            }
        }
        
        return -1;
    }
    
    private List<Integer> getNexts(int cur, List<Integer> colors, Map<Integer, List<Integer>> map, boolean[] visited) {
        List<Integer> nexts = new ArrayList<>();
        int n = colors.size();
        // 向右走
        if (cur + 1 <= n - 1 && !visited[cur + 1]) {
            nexts.add(cur + 1);
        }
        // 如果走到n - 1的位置了,直接返回
        if (nexts.contains(n - 1)) {
            return nexts;
        }
        // 向左走
        if (cur - 1 >= 0 && !visited[cur - 1]) {
            nexts.add(cur - 1);
        }
        
        // 向相同颜色走
        if (map.containsKey(colors.get(cur))) {
            for (int next : map.get(colors.get(cur))) {
                if (next == n - 1) {
                    return Arrays.asList(n - 1);
                }
        
                if (!visited[next]) {
                    nexts.add(next);
                }
            }
        }
        
        return nexts;
    }
}

时空复杂度 O ( n ) O(n) O(n)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值