656 Coin Path

https://leetcode.com/problems/coin-path/description/
首先这道题看上去可以用Dijkstra做。 最小路径嘛,又带了权重,那Dijstra最合适,不过他要求的是path不是 path的长度,所以还得记一个从哪里来的。我最初是思路是从前往后找,然后找完之后从尾向前重建路径。 但是我写完之后发现解决不了lexicographical order的问题。有一个test case“ [0,0,0,0,0,0], 3 ” 解决不了。 果断看答案,发现是用dp而且是从后向前倒推再从前向后重建路径,跟我的作法正好反过来。
这一点比较坑(如何解决lexicographical order),我第二遍做时还是花了不少时间。
下面解释一下我看来的答案。
1。 最外层的顺序从最后一个点开始倒推。每个点的DP状态记录这个点到终点的最少花费。如果从这个点到不了终点,就是-1;
2。对于每个点求他dp值的时候又是从左向右推。这样可以保证lexicographical order。如果后面出现的值和当前一样,那还是留之前的,因为之前的lexicographical order比较小。
这两个trick都是平淡无奇但结合在一起就能完美解决这道题。
后来发现这个挺绕的思路可以直接从recursion + mem推导出来。
如果从recursion的思路就比较直接了。 所以一定要一题会多解,这样这条路遇到问题我们可以从袖子里掏出另外一个trick来。
用Dijkstra方法就不是很方便做。当然我在leetcode论坛上也看到有人用Dijkstra做,不过那个代码实在是太难看了。
下面是DP代码,新手可以略过直接看recursion的。

public List<Integer> cheapestJump(int[] A, int B) {
        int N = A.length; //省得老写A.length好麻烦 
        List<Integer> ans = new LinkedList<>();
        int[] dp = new int[N]; 
        //dp state: the min cost from the end;
        Arrays.fill(dp, -1);
        dp[N - 1] = A[N - 1]; // 初始化
        Map<Integer, Integer> leftRightMap = new HashMap<>();
        // 这个map从左边的点指向他右边的点,
        //由于这里是倒着找的, parentChild有点confusing, 
        //所以用leftRight而不是parentChild, 
        for (int i = N - 2; i >= 0; i--){ //从右向左 
            if (A[i] == -1) continue;
            for (int b = 1; b <= B && b + i < N; b++) { //从左向右
                if (A[b + i] == -1 ||dp[i + b] == -1) continue;
                if (dp[i] == -1 || dp[b + i] + A[i] < dp[i]) {
                    dp[i] = dp[b + i] + A[i];
                    // 现在记一下从i点去哪个点总cost小,
                    leftRightMap.put(i, i + b); 
                }
            }
        }

        if (dp[0] == -1) return ans;
        Integer cur = 0;
        while (cur != null) {
            ans.add(cur + 1);
            cur = leftRightMap.get(cur);
            
        }
        return ans;

用Recursion + memorization的办法解相比就直观多了。
我建议如果面试中如果被问到这道题,先propose recursion + Memorization吧, 这样保证lexicographical order没有问题。下面是代码, 没有DP好看,但好懂呀

  public List<Integer> cheapestJump(int[] A, int B) {
        List<Integer> ans = new LinkedList<>();
        int N = A.length;
        if (A[N - 1] == -1) return ans;
        Map<Integer, Integer> leftRightMap = new HashMap<>();
        Map<Integer, Integer> costMap = new HashMap<>();
        if (cheapestJump(A, B, 0, leftRightMap, costMap, N) == -1) {
            return ans;
        }
        // reconstruct Map;
        Integer cur = 0;
        while (cur != null) {
            ans.add(cur + 1); //indexed from 1
            cur = leftRightMap.get(cur);
        }
        return ans;
    }
    private int cheapestJump(int[] A, int B, int index, 
                             Map<Integer, Integer> leftRightMap,
                             Map<Integer, Integer> costMap, int N) {
        if (index >= N ) return -1;
        if (costMap.containsKey(index)) return costMap.get(index);
        if (index == N - 1 && A[index] != -1) {
            costMap.put(index, A[index]);
            return costMap.get(index);
        }
        if (A[index] == -1) {
            costMap.put(index, -1);
            return costMap.get(index);
        }
        int localMin = -1, right = -1;
        for (int step = 1; step <= B; step++) {
            int cost = cheapestJump(A, B, step + index, leftRightMap, costMap, N);
            if (cost != -1) {
                if (localMin == -1 || cost < localMin){
                    localMin = cost;
                    right = step + index;
                }
            }
        }
        costMap.put(index, localMin != -1 ? localMin + A[index] : -1);
        leftRightMap.put(index, right);
        return costMap.get(index);
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容

  • 动态规划(Dynamic Programming) 本文包括: 动态规划定义 状态转移方程 动态规划算法步骤 最长...
    廖少少阅读 3,252评论 0 18
  • LeetCode 刷题随手记 - 第一部分 前 256 题(非会员),仅算法题,的吐槽 https://leetc...
    蕾娜漢默阅读 17,676评论 2 36
  • 不久前跟室友聊天,突然聊到“无聊”这个词,然后大家就进入了各种的吐槽状态中…… 大家吐槽的中心无外乎都围...
    伊伊烑阅读 404评论 0 1
  • 关羽,是我在看了《三国演义》后,很喜欢的一个人物,他的勇猛,重情重义,都使我对他十分敬佩。 关羽是三国时期的一员虎...
    史卉迪阅读 467评论 0 1
  • 眼泪流了一遍又一遍,心痛了一遍又一遍,原来用心的爱着一个人是这般感受。亲爱的小孩不要哭了。你多么希望你还是曾经的那...
    这样一个女孩阅读 122评论 0 0