转化数字的最小运算数 - 力扣 (LeetCode) 竞赛

175 阅读1分钟

看题目有点迷惑。但是连蒙带猜大概明白是啥意思了,结合数组的范围,推断出来是用BFS来找最小值。

一开始是用set来去重,很奇怪的是虽然报了超时,但是通过的用例是51/51......呵呵。但是至少证明是没猜错的,就是用BFS来搜索

public int minimumOperations(int[] nums, int start, int goal) {

    Queue<Long> queue = new LinkedList<>();
    queue.add((long) start);
    int level = 0;
    Set<Long> visited = new HashSet<>();
    visited.add((long)start);
    while (!queue.isEmpty()) {
        int size = queue.size();
        for (int i = 0; i < size; i++) {
            long current = queue.poll();
            if (current == goal) {
                return level;
            }
            if (0 <= current && current <= 1000) {
                for (int j = 0; j < nums.length; j++) {
                    if (!visited.contains(current + nums[j])) {
                        queue.add(current + nums[j]);
                        visited.add(current + nums[j]);
                    }
                    if (!visited.contains(current - nums[j])) {
                        queue.add(current - nums[j]);
                        visited.add(current - nums[j]);
                    }
                    if (!visited.contains(current ^ nums[j])) {
                        queue.add(current ^ nums[j]);
                        visited.add(current ^ nums[j]);
                    }
                }
            }

        }
        level++;
    }
    return -1;
}

很明显就是因为Set去重导致超时。于是转变想法用数组来表示是否重复,从而bfs剪枝。因此需要先明确数组的范围,看到题目。知道数值是限制在[0,1000]

于是直接这样子改造:

public int minimumOperations(int[] nums, int start, int goal) {

    Queue<Integer> queue = new LinkedList<>();
    queue.add(start);
    int level = 0;
    int[] visited = new int[1001];
    visited[start] = 1;
    while (!queue.isEmpty()) {
        int size = queue.size();
        for (int i = 0; i < size; i++) {
            int current = queue.poll();
            if (current == goal) {
                return level;
            }
            if (0 <= current && current <= 1000) {
                for (int j = 0; j < nums.length; j++) {
                    int a1 = current + nums[j];
                    int a2 = current - nums[j];
                    int a3 = current ^ nums[j];
                    if (visited[a1] == 0) {
                        queue.add(a1);
                        visited[a1] = 1;
                    }
                    if (visited[a2] == 0) {
                        queue.add(a2);
                        visited[a2] = 1;
                    }
                    if (visited[a3] == 0) {
                        queue.add(a3);
                        visited[a3] = 1;
                    }
                }
            }

        }
        level++;
    }
    return -1;
}

但是用测试用例发现下标会有-1这种负数导致越界。

于是又观察了下代码:

if (0 <= current && current <= 1000) {
    for (int j = 0; j < nums.length; j++) {
        int a1 = current + nums[j];
        int a2 = current - nums[j];
        int a3 = current ^ nums[j];
        if (visited[a1] == 0) {
            queue.add(a1);
            visited[a1] = 1;
        }
        if (visited[a2] == 0) {
            queue.add(a2);
            visited[a2] = 1;
        }
        if (visited[a3] == 0) {
            queue.add(a3);
            visited[a3] = 1;
        }
    }
}

发现只有0 <= current && current <= 1000 才需要执行运算,那其实就可以把这个校验提前到这一轮的bfs,不用等到下一轮。于是改造成如下就pass了。

//比赛时写的代码,比较挫

public int minimumOperations(int[] nums, int start, int goal) {

    Queue<Integer> queue = new LinkedList<>();
    queue.add(start);
    int level = 0;
    int[] visited = new int[1010];
    visited[start] = 1;
    while (!queue.isEmpty()) {
        int size = queue.size();
        for (int i = 0; i < size; i++) {
            int current = queue.poll();
            if (current == goal) {
                return level;
            }
            if (0 <= current && current <= 1000) {
                for (int j = 0; j < nums.length; j++) {
                    int a1 = current + nums[j];
                    int a2 = current - nums[j];
                    int a3 = current ^ nums[j];
                    if (a1 == goal || a2 == goal || a3 == goal) {
                        return level + 1;
                    }
                    if (0 <= a1 && a1 <= 1000 && visited[a1] == 0) {
                        queue.add(a1);
                        visited[a1] = 1;
                    }
                    if (0 <= a2 && a2 <= 1000 && visited[a2] == 0) {
                        queue.add(a2);
                        visited[a2] = 1;
                    }
                    if (0 <= a3 && a3 <= 1000 && visited[a3] == 0) {
                        queue.add(a3);
                        visited[a3] = 1;
                    }
                }
            }

        }
        level++;
    }
    return -1;
}