Leetcode 1345. 跳跃游戏 IV

Leetcode 1345. 跳跃游戏 IV

题意:

给一个一维的数组,你从下标0开始出发,有三种操作:每次可以向左,右移动一位,或者移动到与自己数值相同的位置。

思路:

这类搜索求最短步数的解法是典型的bfs,注意这题数据的特殊性,裸bfs会超时。
这是因为第三个操作枚举所有相同数值的位置时候,如果出现很多
相同值的数值,光枚举相同值时间复杂度会近似O(n),整体就变成O(n^2)。

这一步枚举,可以把连续出现相同值的区间只保留左右两个端点,起到搜索剪枝的作用。

代码:

python

class Solution:
    def minJumps(self, arr) -> int:
        import collections
        n = len(arr)
        if n  == 1: return 0
        poss = collections.defaultdict(list)
        for index, value in enumerate(arr):
            if (index and arr[index]!= arr[index-1] or
                    (index < n-1 and arr[index]!=arr[index + 1])): # 剪枝
                poss[value] .append(index)
        que= collections.deque([(0,0)])
        vis = set([0])
        while que:
            pos, cur  = que.popleft()
            for nxt in poss[arr[pos]] + [pos+1 ,pos -1]:
                if nxt == n -1: return cur +1
                if 0 < nxt < n-1 and nxt not in vis:
                    que.append((nxt , cur+1))
                    vis.add(nxt)

c++

class Solution {
public:
    int minJumps(vector<int>& arr) {
        int n = arr.size();
        if(n==1) return 0;
        unordered_map<int, vector<int>> pos;
        for(int i =0 ;i<n;i++){
            if((i>0&&arr[i]!=arr[i-1])||(i<n-1&&arr[i]!=arr[i+1])){
                pos[arr[i]].push_back(i);
            }
        }
        queue<pair<int,int> > que;
        que.push(make_pair(0 ,0));
        set<int> vis;
        vis.insert(0);
        int ans =0 ;
        bool flag = false;
        while(!que.empty()){
            int p = que.front().first, cur = que.front().second;
            que.pop();
            for(int i=0;i<pos[arr[p]].size();i++){
                int nxt = pos[arr[p]][i];
                if((nxt == n-1)||(p+1 == n-1)){
                        ans = cur + 1;
                        flag = true;
                        break;
                }
                if(nxt>1&&nxt<n&&vis.count(nxt)==0){
                    que.push(make_pair(nxt, cur+1));
                    vis.insert(nxt);
                }
            }
            if(flag) break;
            if(p+1>0&&p+1<n&&vis.count(p+1)==0){
                que.push(make_pair(p+1, cur+1));
                vis.insert(p+1);
            }
            if(p-1>0&&p-1<n&&vis.count(p-1)==0){
                que.push(make_pair(p-1, cur+1));
                vis.insert(p-1);
            }
        }
        return ans;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值