6439. Minimum String Length After Removing Substrings

给你一个仅由 大写 英文字符组成的字符串 s 。

你可以对此字符串执行一些操作,在每一步操作中,你可以从 s 中删除 任一个 "AB" 或 "CD" 子字符串。

通过执行操作,删除所有 "AB" 和 "CD" 子串,返回可获得的最终字符串的 最小 可能长度。

注意,删除子串后,重新连接出的字符串可能会产生新的 "AB" 或 "CD" 子串。

测试样例:

输入:s = "ABFCACDB"

输出:2

解释:
你可以执行下述操作:

  • 从 "ABFCACDB" 中删除子串 "AB",得到 s = "FCACDB" 。
  • 从 "FCACDB" 中删除子串 "CD",得到 s = "FCAB" 。
  • 从 "FCAB" 中删除子串 "AB",得到 s = "FC" 。

最终字符串的长度为 2 。可以证明 2 是可获得的最小长度。

解答:利用栈的特性,可以完成递归删除。

class Solution {
    public int minLength(String s) {
        Stack<Character> stack = new Stack<>();
        for (int i = 0; i < s.length(); ++i) {
            if (s.charAt(i) == 'B') {
                if (!stack.isEmpty() && stack.peek() == 'A') {
                    stack.pop();
                    continue;
                }
            }
            if (s.charAt(i) == 'D') {
                if (!stack.isEmpty() && stack.peek() == 'C') {
                    stack.pop();
                    continue;
                }
            }
            stack.push(s.charAt(i));
        }
        return stack.size();
    }
}

6454. Lexicographically Smallest Palindrome

给你一个由 小写英文字母 组成的字符串 s ,你可以对其执行一些操作。在一步操作中,你可以用其他小写英文字母 替换 s 中的一个字符。

请你执行 尽可能少的操作 ,使 s 变成一个 回文串 。如果执行 最少 操作次数的方案不止一种,则只需选取 字典序最小 的方案。

对于两个长度相同的字符串 a 和 b ,在 a 和 b 出现不同的第一个位置,如果该位置上 a 中对应字母比 b 中对应字母在字母表中出现顺序更早,则认为 a 的字典序比 b 的字典序要小。

返回最终的回文字符串。

测试样例:

输入:s = "egcfe"

输出:"efcfe"

解释:
将 "egcfe" 变成回文字符串的最小操作次数为 1 ,修改 1 次得到的字典序最小回文字符串是 "efcfe",只需将 'g' 改为 'f' 。

解答:因为操作次数最小,有需要字典序最小。那就是应该相同的位置选择较小的char就行了

class Solution {
    public String makeSmallestPalindrome(String s) {
        int st = 0, ed = s.length() - 1;
        StringBuilder sb = new StringBuilder();
        while (st < ed) {
            char c = (char) Math.min(s.charAt(st), s.charAt(ed));
            sb.append(c);
            ++st;
            --ed;
        }
        String tmp = sb.toString();
        if (st == ed) {
            tmp += s.charAt(st);
        }
        String rev = sb.reverse().toString();
        return tmp + rev;
    }
}

6441. Find the Punishment Number of an Integer

给你一个正整数 n ,请你返回 n 的 惩罚数 。

n 的 惩罚数 定义为所有满足以下条件 i 的数的平方和:

  • 1 <= i <= n
  • i * i 的十进制表示的字符串可以分割成若干连续子字符串,且这些子字符串对应的整数值之和等于 i 。

测试样例

输入:n = 10

输出:182

解释:
总共有 3 个整数 i 满足要求:

  • 1 ,因为 1 * 1 = 1
  • 9 ,因为 9 * 9 = 81 ,且 81 可以分割成 8 + 1 。
  • 10 ,因为 10 * 10 = 100 ,且 100 可以分割成 10 + 0 。

因此,10 的惩罚数为 1 + 81 + 100 = 182

解答:这道题范围极小,寻找符合要求的数字计算一下。

class Solution {
    private static final int[] valid = {1,9,10,36,45,55,82,91,99,100,235,297,369,370,379,414,657,675,703,756,792,909,918,945,964,990,991,999,1000};

    public int punishmentNumber(int n) {
        int res = 0;
        for (int i : valid) {
            if (i <= n) {
                res += i * i;
            }
        }
        return res;
    }

    private boolean isValid(int n) {
        int tmp = n * n;
        return isFound(String.valueOf(tmp), 0, n, 0, 0);
    }

    private boolean isFound(String tmp, int pos, int res, int add, int last) {
        if (pos == tmp.length()) {
            return add + last == res;
        } else {
            int p = tmp.charAt(pos) - '0';
            return isFound(tmp, pos + 1, res, add + last, p) || isFound(tmp, pos + 1, res, add, last * 10 + p);
        }
    }
}

6442. Modify Graph Edge Weights

给你一个 n 个节点的 无向带权连通 图,节点编号为 0 到 n - 1 ,再给你一个整数数组 edges ,其中 edges[i] = [ai, bi, wi] 表示节点 ai 和 bi 之间有一条边权为 wi 的边。

部分边的边权为 -1(wi = -1),其他边的边权都为 正 数(wi > 0)。

你需要将所有边权为 -1 的边都修改为范围 [1, 2 * 109] 中的 正整数 ,使得从节点 source 到节点 destination 的 最短距离 为整数 target 。如果有 多种 修改方案可以使 source 和 destination 之间的最短距离等于 target ,你可以返回任意一种方案。

如果存在使 source 到 destination 最短距离为 target 的方案,请你按任意顺序返回包含所有边的数组(包括未修改边权的边)。如果不存在这样的方案,请你返回一个 空数组 。

注意:你不能修改一开始边权为正数的边。

测试样例

输入:n = 5, edges = [[4,1,-1],[2,0,-1],[0,3,-1],[4,3,-1]], source = 0, destination = 1, target = 5

输出:[[4,1,1],[2,0,1],[0,3,3],[4,3,1]]

解释:

从 0 到 1 的最短距离为 5 。

解答:这道题目,n的范围很小。所以也可以使用暴力算法寻找任意2点之间的最小距离

class Solution {
    private static final int MAX = 2_000_000_000;

    public int[][] modifiedGraphEdges(int n, int[][] edges, int ss, int tt, int target) {
        int m = edges.length;
        ArrayDeque <int[]> neg = new ArrayDeque();
        long[][] dis = new long[n][n];
        boolean valid = false;
        for(int i = 0; i < n; i++) Arrays.fill(dis[i], MAX);
        for(int i = 0; i < n; i++) dis[i][i] = 0;
        for(int i = 0; i < m; i++) {
            if(edges[i][2] < 0) neg.add(new int[]{edges[i][0], edges[i][1], edges[i][2], i});
            else dis[edges[i][0]][edges[i][1]] = dis[edges[i][1]][edges[i][0]] = edges[i][2];
        }
        for(int k = 0; k < n; k++) {
            for(int i = 0; i < n; i++) {
                for(int j = 0; j < n; j++) {
                    dis[i][j] = dis[j][i] = Math.min(dis[i][j], dis[i][k] + dis[j][k]);
                }
            }
        }
        if(dis[ss][tt] < target) return new int[0][3];
        for (int[] ee : neg) {
            int a = ee[0], b = ee[1], d = ee[3];
            long min = Math.min(dis[ss][a] + dis[tt][b], dis[ss][b] + dis[tt][a]);
            if (min < target) {
                edges[d][2] = (int) (target - min);
                valid = true;
                break;
            } else {
                dis[a][b] = dis[b][a] = 1;
                edges[d][2] = 1;
                for(int i = 0; i < n; i++) {
                    for(int j = 0; j < i; j++) {
                        dis[i][j] = dis[j][i] = Math.min(dis[i][j], 1 + Math.min(dis[i][a] + dis[j][b], dis[i][b] + dis[j][a]));
                    }
                }
            }
        }
        if (dis[ss][tt] == target) valid = true;
        if (!valid) return new int[0][3];
        for(int i = 0; i < m; i++) if (edges[i][2] == -1) edges[i][2] = MAX;
        return edges;
    }
}

Leave a Reply

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