100245. 每个字符最多出现两次的最长子字符串

给你一个字符串 s ,请找出满足每个字符最多出现两次的最长子字符串,并返回该子字符串的 最大 长度。

测试样例:

输入:s = "bcbbbcba"

输出:4

解释:以下子字符串长度为 4,并且每个字符最多出现两次:"bcbbbcba"。

解答:s.length <= 100, 直接无脑暴力。

class Solution {
    public int maximumLengthSubstring(String s) {
        int res = 0;
        for (int i = 0; i < s.length(); ++i) {
            for (int j = i; j < s.length(); ++j) {
                if (isValid(s, i, j)) {
                    res = Math.max(res, j - i + 1);
                }
            }
        }
        return res;
    }

    private boolean isValid(String s, int st, int ed) {
        int[] count = new int[256];
        for (int i = st; i <= ed; ++i) {
            char c = s.charAt(i);
            count[c] += 1;
            if (count[c] > 2) {
                return false;
            }
        }
        return true;
    }
}

100228. 执行操作使数据元素之和大于等于 K

给你一个正整数 k 。最初,你有一个数组 nums = [1] 。

你可以对数组执行以下 任意 操作 任意 次数(可能为零):

  • 选择数组中的任何一个元素,然后将它的值 增加 1 。
  • 复制数组中的任何一个元素,然后将它附加到数组的末尾。

返回使得最终数组元素之 和 大于或等于 k 所需的 最少 操作次数。

测试样例:

输入:k = 11

输出:5

解释:可以对数组 nums = [1] 执行以下操作:

  • 将元素的值增加 1 三次。结果数组为 nums = [4] 。
  • 复制元素两次。结果数组为 nums = [4,4,4] 。

最终数组的和为 4 + 4 + 4 = 12 ,大于等于 k = 11 。执行的总操作次数为 3 + 2 = 5 。

解答:最优的方案一定是先进行一定数量的操作1,然后进行操作2(如果不是先1后2,那么将操作2放在操作1之后,总和必然大于混合的操作)。这样,直接枚举一定数量的次数即可。

class Solution {
    public int minOperations(int k) {
        int min = k - 1;
        for (int i = 1; i < k; ++i) {
            int num = i + 1;
            int time = k / num + (k % num == 0 ? 0 : 1) - 1;
            min = Math.min(i + time, min);
        }
        return min;
    }
}

100258. 最高频率的 ID

你需要在一个集合里动态记录 ID 的出现频率。给你两个长度都为 n 的整数数组 nums 和 freq ,nums 中每一个元素表示一个 ID ,对应的 freq 中的元素表示这个 ID 在集合中此次操作后需要增加或者减少的数目。

  • 增加 ID 的数目:如果 freq[i] 是正数,那么 freq[i] 个 ID 为 nums[i] 的元素在第 i 步操作后会添加到集合中。
  • 减少 ID 的数目:如果 freq[i] 是负数,那么 -freq[i] 个 ID 为 nums[i] 的元素在第 i 步操作后会从集合中删除。

请你返回一个长度为 n 的数组 ans ,其中 ans[i] 表示第 i 步操作后出现频率最高的 ID 数目 ,如果在某次操作后集合为空,那么 ans[i] 为 0 。

测试样例:

输入:nums = [2,3,2,1], freq = [3,2,-3,1]

输出:[3,3,2,2]

解释:

  • 第 0 步操作后,有 3 个 ID 为 2 的元素,所以 ans[0] = 3 。
  • 第 1 步操作后,有 3 个 ID 为 2 的元素和 2 个 ID 为 3 的元素,所以 ans[1] = 3 。
  • 第 2 步操作后,有 2 个 ID 为 3 的元素,所以 ans[2] = 2 。
  • 第 3 步操作后,有 2 个 ID 为 3 的元素和 1 个 ID 为 1 的元素,所以 ans[3] = 2 。

解答:对频率用TreeMap计数,每次读取最高频次的数。

class Solution {
    public long[] mostFrequentIDs(int[] nums, int[] freq) {
        int len = nums.length;
        Map<Integer, Long> countMap = new HashMap<>();
        TreeMap<Long, Integer> freqMap = new TreeMap<>();
        freqMap.put(0L, 0);
        long[] res = new long[len];
        for (int i = 0; i < len; ++i) {
            int n = nums[i], f = freq[i];
            long oldFreq = countMap.getOrDefault(n, 0L);
            if (oldFreq != 0) {
                int ct = freqMap.get(oldFreq);
                if (ct == 1) {
                    freqMap.remove(oldFreq);
                } else {
                    freqMap.put(oldFreq, ct - 1);
                }
            }
            oldFreq += f;
            countMap.put(n, oldFreq);
            freqMap.put(oldFreq, freqMap.getOrDefault(oldFreq, 0) + 1);
            res[i] = freqMap.lastKey();
        }
        return res;
    }
}

100268. 最长公共后缀查询

给你两个字符串数组 wordsContainer 和 wordsQuery 。

对于每个 wordsQuery[i] ,你需要从 wordsContainer 中找到一个与 wordsQuery[i] 有 最长公共后缀 的字符串。如果 wordsContainer 中有两个或者更多字符串有最长公共后缀,那么答案为长度 最短 的。如果有超过两个字符串有 相同 最短长度,那么答案为它们在 wordsContainer 中出现 更早 的一个。

请你返回一个整数数组 ans ,其中 ans[i]是 wordsContainer中与 wordsQuery[i] 有 最长公共后缀 字符串的下标。

测试样例:

输入:wordsContainer = ["abcd","bcd","xbcd"], wordsQuery = ["cd","bcd","xyz"]

输出:[1,1,1]

解释:我们分别来看每一个 wordsQuery[i] :

  • 对于 wordsQuery[0] = "cd" ,wordsContainer 中有最长公共后缀 "cd" 的字符串下标分别为 0 ,1 和 2 。这些字符串中,答案是下标为 1 的字符串,因为它的长度为 3 ,是最短的字符串。
  • 对于 wordsQuery[1] = "bcd" ,wordsContainer 中有最长公共后缀 "bcd" 的字符串下标分别为 0 ,1 和 2 。这些字符串中,答案是下标为 1 的字符串,因为它的长度为 3 ,是最短的字符串。
  • 对于 wordsQuery[2] = "xyz" ,wordsContainer 中没有字符串跟它有公共后缀,所以最长公共后缀为 "" ,下标为 0 ,1 和 2 的字符串都得到这一公共后缀。这些字符串中, 答案是下标为 1 的字符串,因为它的长度为 3 ,是最短的字符串。

解答:这周手速场了,利用TrieTree可以快速搜索最长后缀和。唯一对TrieTree唯一需要修改的,就是记录一下当前后缀,符合最短字符串(或者最短的情况下,最早出现的序号)。

class Solution {
    private class TrieNode {
        HashMap<Character, TrieNode> next;
        Comparator<Integer> comparator;
        int best;

        public TrieNode(Comparator<Integer> compare) {
            next = new HashMap<>();
            best = -1;
            this.comparator = compare;
        }

        public void updateBest(int val) {
            if (best == -1 || comparator.compare(best, val) > 0) {
                best = val;
            }
        }
    }

    private class IntegerCompare implements Comparator<Integer> {
        private String[] wordsContainer;

        public IntegerCompare(String[] wordsContainer) {
            this.wordsContainer = wordsContainer;
        }

        @Override
        public int compare(Integer o1, Integer o2) {
            if (wordsContainer[o1].length() != wordsContainer[o2].length()) {
                return Integer.compare(wordsContainer[o1].length(), wordsContainer[o2].length());
            } else {
                return o1.compareTo(o2);
            }
        }
    }

    public int[] stringIndices(String[] wordsContainer, String[] wordsQuery) {
        IntegerCompare compare = new IntegerCompare(wordsContainer);
        TrieNode root = new TrieNode(compare);
        for (int i = 0; i < wordsContainer.length; ++i) {
            TrieNode tmp = root;
            root.updateBest(i);
            for (int j = wordsContainer[i].length() - 1; j >= 0; --j) {
                char c = wordsContainer[i].charAt(j);
                if (!tmp.next.containsKey(c)) {
                    tmp.next.put(c, new TrieNode(compare));
                }
                tmp = tmp.next.get(c);
                tmp.updateBest(i);
            }
        }

        int[] res = new int[wordsQuery.length];
        for (int i = 0; i < wordsQuery.length; ++i) {
            String w = wordsQuery[i];
            TrieNode tmp = root;
            res[i] = tmp.best;
            for (int j = w.length() - 1; j >= 0; --j) {
                char c = w.charAt(j);
                if (tmp.next.containsKey(c)) {
                    tmp = tmp.next.get(c);
                    res[i] = tmp.best;
                } else {
                    break;
                }
            }
        }
        return res;
    }
}

Leave a Reply

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