Leetcode 752 打开转盘锁 扩散查询

  问题的遍历可以通过按顺序尝试每一个锁的所有可能,但是因为需要记录转动次数。尝试可能性的时候并不能很好的记录转动次数。

  以转动次数为遍历的线,将每转动一次的所有可能进行记录,并以此为基础计算下一次转动的所有可能性。

  当惯用的遍历方式不适合解题时,找到矛盾的点,从矛盾点出发考虑新的遍历方式。

  当视角放在局部(一个锁一个锁的尝试可能性)不能很好地解决问题时,将视角拉到整体(转动一次整体的所有可能)。

  找到矛盾点,视角的灵活转换从来都是解决问题的根本性思路。

  JAVA:

public final int openLock(String[] deadends, String target) {
        Set<String> deadSet = new HashSet<String>(), history = new HashSet<String>();
        for (int i = 0; i < deadends.length; i++) deadSet.add(deadends[i]);
        Queue<String> queue = new LinkedList<String>();
        insert("0000", queue, deadSet, history);
        int currStep = 0;
        while (!queue.isEmpty()) {
            int len = queue.size();
            for (int i = 0; i < len; i++) {
                String current = queue.poll();
                if (target.equals(current)) return currStep;
                for (int j = 0; j < 4; j++) {
                    String right = this.moveRight(current, j);
                    String left = this.moveLeft(current, j);
                    this.insert(right, queue, deadSet, history);
                    this.insert(left, queue, deadSet, history);
                }
            }
            currStep++;
        }
        return -1;
    }

    private final void insert(String source, Queue<String> queue, Set<String> deads, Set<String> history) {
        if (deads.contains(source) || history.contains(source)) return;
        history.add(source);
        queue.offer(source);
    }

    private final String moveLeft(String source, int target) {
        return this.move(source, target, -1);
    }

    private final String moveRight(String source, int target) {
        return this.move(source, target, 1);
    }

    private final String move(String source, int target, int added) {
        int pre = source.charAt(target) - '0';
        int next = (pre + added + 10) % 10;
        String re = source.substring(0, target) + next + source.substring(target + 1, source.length());
        return re;
    }

  JS:

/**
 * @param {string[]} deadends
 * @param {string} target
 * @return {number}
 */
var openLock = function (deadends, target) {
    if ("0000" == target) return 0;
    let deadSet = new Set(), his = new Set(), queue = [], re = 0;
    for (let i = 0; i < deadends.length; i++) deadSet.add(deadends[i]);
    if (deadSet.has("0000")) return -1;
    queue.push("0000");
    his.add("0000");
    while (queue.length > 0) {
        let currentLen = queue.length;
        for (let j = 0; j < currentLen; j++) {
            let currentVal = queue.shift();
            for (let k = 0; k < 4; k++) {
                let left = spanLeft(currentVal, k), right = spanRight(currentVal, k);
                if (!his.has(left) && !deadSet.has(left)) {
                    his.add(left);
                    queue.push(left);
                    if (target == left) return re + 1;
                }
                if (!his.has(right) && !deadSet.has(right)) {
                    queue.push(right);
                    his.add(right);
                    if (target == right) return re + 1;
                }
            }
        }
        re++;
    }
    return -1;
};

var spanRight = function (pre, point) {
    return span(pre, point, 1);
}

var spanLeft = function (pre, point) {
    return span(pre, point, -1);
}

var span = function (pre, point, added) {
    let curr = (parseInt(pre.charAt(point)) + added + 10) % 10;
    return pre.substring(0, point) + curr + pre.substring(point + 1, pre.length)
}

 

posted @ 2021-05-09 15:47  牛有肉  阅读(70)  评论(0编辑  收藏  举报