欢迎大家加QQ群:623375442,可以方便群里面交流。

100422. Convert Date to Binary

给你一个字符串 date,它的格式为 yyyy-mm-dd,表示一个公历日期。

date 可以重写为二进制表示,只需要将年、月、日分别转换为对应的二进制表示(不带前导零)并遵循 year-month-day 的格式。

返回 date 的 二进制 表示。

测试样例:

输入:date = "2080-02-29"

输出:"100000100000-10-11101"

解释:100000100000, 10 和 11101 分别是 2080, 02 和 29 的二进制表示。

解答:暴力拆分,然后转成二进制。Java的API还是挺全的。

class Solution {
    public String convertDateToBinary(String date) {
        String[] split = date.split("-");
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 3; ++i) {
            if (sb.length() > 0) {
                sb.append('-');
            }
            sb.append(Integer.toBinaryString(Integer.parseInt(split[i])));
        }
        return sb.toString();
    }
}

100353. Maximize Score of Numbers in Ranges

给你一个整数数组 start 和一个整数 d,代表 n 个区间 [start[i], start[i] + d]。

你需要选择 n 个整数,其中第 i 个整数必须属于第 i 个区间。所选整数的 得分 定义为所选整数两两之间的 最小 绝对差。

返回所选整数的 最大可能得分 。

测试样例:

输入:start = [6,0,3], d = 2

输出:4

解释:可以选择整数 8, 0 和 4 获得最大可能得分,得分为 min(|8 - 0|, |8 - 4|, |0 - 4|),等于 4。

解答:利用折半搜索寻找最大值。这题需要想到,最小绝对差越大,则越不容易实现。

class Solution {
    public int maxPossibleScore(int[] start, int d) {
        Arrays.sort(start);
        int st = 0, ed = start[start.length - 1] + d - start[0];
        while (st < ed) {
            int mid = st + (ed - st + 1) / 2;
            if (isValid(start, d, mid)) {
                st = mid;
            } else {
                ed = mid - 1;
            }
        }
        return st;
    }

    private boolean isValid(int[] start, int d, int mid) {
        long pos = start[0];
        // 贪婪的寻找下一个最优数,越小越好。
        for (int i = 1; i < start.length; ++i) {
            pos += mid;
            if (pos > start[i] + d) {
                return false;
            }
            pos = Math.max(start[i], pos);
        }
        return true;
    }
}

100389. Reach End of Array With Max Score

给你一个长度为 n 的整数数组 nums 。

你的目标是从下标 0 出发,到达下标 n - 1 处。每次你只能移动到 更大 的下标处。

从下标 i 跳到下标 j 的得分为 (j - i) * nums[i] 。

请你返回你到达最后一个下标处能得到的 最大总得分 。

测试样例:

输入:nums = [1,3,1,5]

输出:7

解释:一开始跳到下标 1 处,然后跳到最后一个下标处。总得分为 1 1 + 2 3 = 7 。

解答:重点是贪婪,得分是(j - i) * nums[i],所以每次碰到一个比当前大的数值,就立刻停下,然后完成一次跳跃。

class Solution {
    public long findMaximumScore(List<Integer> _nums) {
        int[] nums = new int[_nums.size()];
        int p = 0;
        for (int n : _nums) {
            nums[p++] = n;
        }
        long[] dp = new long[nums.length];
        Stack<Integer> stack = new Stack<>();
        for (int i = nums.length - 1; i >= 0; --i) {
            while (!stack.isEmpty() && nums[stack.peek()] <= nums[i]) {
                stack.pop();
            }
            if (stack.isEmpty()) {
                dp[i] = (nums.length - 1L - i) * nums[i];
            } else {
                dp[i] = ((long) stack.peek() - i) * nums[i] + dp[stack.peek()];
            }
            stack.push(i);
        }
        return dp[0];
    }
}

补一个群友的,更好的解答。没必要用单调栈

class Solution {
    public long findMaximumScore(List<Integer> nums) {
          int n = nums.size();
        if(n == 1) return 0;
        int mx = nums.get(0);
        long ans = mx;
        for(int i = 1; i < n - 1; i++){
             if(mx < nums.get(i))
                 mx = nums.get(i);
            ans += mx;
        }
        return ans;
    }
}

100416. Maximum Number of Moves to Kill All Pawns

给你一个 50 x 50 的国际象棋棋盘,棋盘上有 一个 马和一些兵。给你两个整数 kx 和 ky ,其中 (kx, ky) 表示马所在的位置,同时还有一个二维数组 positions ,其中 positions[i] = [xi, yi] 表示第 i 个兵在棋盘上的位置。

Alice 和 Bob 玩一个回合制游戏,Alice 先手。玩家的一次操作中,可以执行以下操作:

  • 玩家选择一个仍然在棋盘上的兵,然后移动马,通过 最少 的 步数 吃掉这个兵。注意 ,玩家可以选择 任意 一个兵,不一定 要选择从马的位置出发 最少 移动步数的兵。
  • 在马吃兵的过程中,马 可能 会经过一些其他兵的位置,但这些兵 不会 被吃掉。只有 选中的兵在这个回合中被吃掉。

Alice 的目标是 最大化 两名玩家的 总 移动次数,直到棋盘上不再存在兵,而 Bob 的目标是 最小化 总移动次数。

假设两名玩家都采用 最优 策略,请你返回 Alice 可以达到的 最大 总移动次数。

在一次 移动 中,如下图所示,马有 8 个可以移动到的位置,每个移动位置都是沿着坐标轴的一个方向前进 2 格,然后沿着垂直的方向前进 1 格。

测试样例:

输入:kx = 1, ky = 1, positions = [[0,0]]

输出:4

解释:马需要移动 4 步吃掉 (0, 0) 处的兵。

解答:这题总体分成2步:

  1. 利用BFS搜索出每一个兵到棋盘上各个位置的最小跳数
  2. 利用动态规划,在Alice轮寻找最大跳数,Bob轮寻找最小跳数

class Solution {
    private static final int[][] moves = {{1,2},{1,-2},{-1,2},{-1,-2},{2,1},{2,-1},{-2,1},{-2,-1}};

    private class Data {
        public int[][][] dis;
        public int[][] positions;
        public Integer[][] dp;
        public int kx, ky;

        public Data(int[][] positions, int kx, int ky) {
            this.positions = positions;
            this.dis = new int[positions.length][][];
            for (int i = 0; i < positions.length; ++i) {
                int[] pos = positions[i];
                dis[i] = findLeastDis(pos);
            }
            dp = new Integer[positions.length][1 << positions.length];
            this.kx = kx;
            this.ky = ky;
        }

        private int[][] findLeastDis(int[] pos) {
            int[][] distance = new int[50][50];
            for (int i = 0; i < 50; ++i) {
                for (int j = 0; j < 50; ++j) {
                    distance[i][j] = Integer.MAX_VALUE;
                }
            }
            distance[pos[0]][pos[1]] = 0;
            // 利用BFS寻找到每个兵,最小的跳数
            Queue<int[]> queue = new LinkedList<>();
            queue.add(pos);
            while (!queue.isEmpty()) {
                int[] first = queue.poll();
                int oldDis = distance[first[0]][first[1]];
                for (int[] mv : moves) {
                    int xt = first[0] + mv[0], yt = first[1] + mv[1];
                    if (xt >= 0 && xt < 50 && yt >= 0 && yt < 50 && distance[xt][yt] == Integer.MAX_VALUE) {
                        queue.add(new int[]{xt, yt});
                        distance[xt][yt] = oldDis + 1;
                    }
                }
            }
            return distance;
        }
    }

    public int maxMoves(int kx, int ky, int[][] positions) {
        Data data = new Data(positions, kx, ky);
        return dfs(-1, 0, 0, data);
    }

    // 使用了带记忆DFS,模拟动态规划,正向有点想不到怎么做
    private int dfs(int offset, int mark, int count, Data data) {
        // 所有兵都吃完了,这个时候跳出计算
        if (mark == (1 << data.positions.length) - 1) {
            return 0;
        }
        if (offset == -1 || data.dp[offset][mark] == null) {
            int x, y;
            if (offset == -1) {
                x = data.kx;
                y = data.ky;
            } else {
                x = data.positions[offset][0];
                y = data.positions[offset][1];
            }
            int res = count == 0 ? Integer.MIN_VALUE : Integer.MAX_VALUE;
            for (int i = 0; i < data.positions.length; ++i) {
                if (!isUsed(mark, i)) {
                    if (count == 0) {
                        // Alice轮寻找最大跳数
                        res = Math.max(res, dfs(i, mark + (1 << i),1, data) + data.dis[i][x][y]);
                    } else {
                        // Bob轮寻找最大跳数
                        res = Math.min(res, dfs(i, mark + (1 << i),0, data) + data.dis[i][x][y]);
                    }
                }
            }
            if (offset != -1) {
                data.dp[offset][mark] = res;
            }
            return res;
        }
        return data.dp[offset][mark];
    }

    private boolean isUsed(int mark, int offset) {
        int tmp = (mark >> offset) & 1;
        return tmp == 1;
    }
}

Leave a Reply

Your email address will not be published. Required fields are marked *