力扣第 119 场双周赛(Java)

文章目录

    • T1 找到两个数组中的公共元素
      • 代码解释
    • T2 消除相邻近似相等字符
      • 代码解释
    • T3 最多 K 个重复元素的最长子数组
      • 代码解释
    • T4 关闭分部的可行集合数目
      • 代码解释

链接:第 119 场双周赛 - 力扣(LeetCode)

T1 找到两个数组中的公共元素

给你两个下标从 0 开始的整数数组 nums1nums2 ,它们分别含有 nm 个元素。

请你计算以下两个数值:

统计 0 <= i < n 中的下标 i ,满足 nums1[i]nums2 中 至少 出现了一次。
统计 0 <= i < m 中的下标 i ,满足 nums2[i]nums1 中 至少 出现了一次。
请你返回一个长度为 2 的整数数组 answer ,按顺序 分别为以上两个数值。

示例 :

输入:nums1 = [4,3,2,3,1], nums2 = [2,2,5,2,3,6]
输出:[3,4]
解释:分别计算两个数值:

  • nums1 中下标为 1 ,2 和 3 的元素在 nums2 中至少出现了一次,所以第一个值为 3 。
  • nums2 中下标为 0 ,1 ,3 和 4 的元素在 nums1 中至少出现了一次,所以第二个值为 4 。

提示:

  • n == nums1.length
  • m == nums2.length
  • 1 <= n, m <= 100
  • 1 <= nums1[i], nums2[i] <= 100

代码解释

暴力 O(n^2)

class Solution {
    public int[] findIntersectionValues(int[] nums1, int[] nums2) {
        int[] ans = new int[]{0, 0};
        for (int k : nums1) {
            for (int i : nums2) {
                if (k == i) {
                    ans[0]++;
                    break;
                }
            }
        }
        for (int k : nums2) {
            for (int i : nums1) {
                if (k == i) {
                    ans[1]++;
                    break;
                }
            }
        }
        return ans;
    }
}

T2 消除相邻近似相等字符

给你一个下标从 0 开始的字符串 word

一次操作中,你可以选择 word 中任意一个下标 i ,将 word[i] 修改成任意一个小写英文字母。

请你返回消除 word 中所有相邻 近似相等 字符的 最少 操作次数。

两个字符 ab 如果满足 a == b 或者 ab 在字母表中是相邻的,那么我们称它们是 近似相等 字符。

示例 1:

输入:word = “aaaaa”
输出:2
解释:我们将 word 变为 “acaca” ,该字符串没有相邻近似相等字符。 消除 word 中所有相邻近似相等字符最少需要 2 次操作。

示例 2:

输入:word = “abddez”
输出:2
解释:我们将 word 变为 “ybdoez” ,该字符串没有相邻近似相等字符。 消除 word 中所有相邻近似相等字符最少需要 2 次操作。

示例 3:

输入:word = “zyxyxyz”
输出:3
解释:我们将 word 变为 “zaxaxaz” ,该字符串没有相邻近似相等字符。 消除 word 中所有相邻近似相等字符最少需要 3 次操作

提示:

  • 1 <= word.length <= 100
  • word 只包含小写英文字母。

代码解释

一次遍历,相邻近似相等字符换一次右边的就是操作次数最少的

class Solution {
    public int removeAlmostEqualCharacters(String word) {
        int ans = 0;
        for (int i = 1; i < word.length(); i++) {
            if (Math.abs(word.charAt(i) - word.charAt(i-1)) < 2) {
                ans++;
                i++;
            }
        }
        return ans;
    }
}

T3 最多 K 个重复元素的最长子数组

给你一个整数数组 nums 和一个整数 k

一个元素 x 在数组中的 频率 指的是它在数组中的出现次数。

如果一个数组中所有元素的频率都 小于等于 k ,那么我们称这个数组是 数组。

请你返回 nums最长好 子数组的长度。

子数组 指的是一个数组中一段连续非空的元素序列。

示例 1:

输入:nums = [1,2,3,1,2,3,1,2], k = 2
输出:6
解释:最长好子数组是 [1,2,3,1,2,3] ,值 1,2 和 3 在子数组中的频率都没有超过 k = 2 。[2,3,1,2,3,1] 和 [3,1,2,3,1,2] 也是好子数组。最长好子数组的长度为 6 。

示例 2:

输入:nums = [1,2,1,2,1,2,1,2], k = 1
输出:2
解释:最长好子数组是 [1,2] ,值 1 和 2 在子数组中的频率都没有超过 k = 1 。[2,1] 也是好子数组。 最长好子数组的长度为 2 。

示例 3:

输入:nums = [5,5,5,5,5,5,5], k = 4
输出:4
解释:最长好子数组是 [5,5,5,5] ,值 5 在子数组中的频率没有超过 k = 4 。 最长好子数组的长度为 4 。

提示:

  • 1 <= nums.length <= 10^5
  • 1 <= nums[i] <= 10^9
  • 1 <= k <= nums.length

代码解释

滑动窗口,哈希表记次数大于 K 时左边界右移,时间复杂度 O(n)

class Solution {
    public int maxSubarrayLength(int[] nums, int k) {
        int ans = 0, l = 0, r = 0, n = nums.length;
        Map<Integer, Integer> map = new HashMap<>();
        while (r < n) {
            map.put(nums[r], map.getOrDefault(nums[r], 0) + 1);
            while (map.get(nums[r]) > k) {
                map.put(nums[l], map.get(nums[l]) - 1);
                l++;
            }
            ans = Math.max(ans, ++r - l);
        }
        return ans;
    }
}

T4 关闭分部的可行集合数目

一个公司在全国有 n 个分部,它们之间有的有道路连接。一开始,所有分部通过这些道路两两之间互相可以到达。

公司意识到在分部之间旅行花费了太多时间,所以它们决定关闭一些分部(也可能不关闭任何分部),同时保证剩下的分部之间两两互相可以到达且最远距离不超过 maxDistance

两个分部之间的 距离 是通过道路长度之和的 最小值

给你整数 nmaxDistance 和下标从 0 开始的二维整数数组 roads ,其中 roads[i] = [ui, vi, wi] 表示一条从 uivi 长度为 wi无向 道路。

请你返回关闭分部的可行方案数目,满足每个方案里剩余分部之间的最远距离不超过 maxDistance

注意,关闭一个分部后,与之相连的所有道路不可通行。

注意,两个分部之间可能会有多条道路。

提示:

  • 1 <= n <= 10
  • 1 <= maxDistance <= 105
  • 0 <= roads.length <= 1000
  • roads[i].length == 3
  • 0 <= ui, vi <= n - 1
  • ui != vi
  • 1 <= wi <= 1000
  • 一开始所有分部之间通过道路互相可以到达。

代码解释

这次最后一题比较简单,就是 位运算 可以将每个节点选就是 1 不选就是 0,使用 弗洛伊德算法(Floyd) 求最短路,时间复杂度最坏为 O ( 2 n n 3 ) O(2^nn^3) O(2nn3)

class Solution {
    public int numberOfSets(int n, int maxDistance, int[][] roads) {
        int ans = 0;
        int[][] g = new int[n][n];
        for (int s = (1 << n) - 1; s >= 0; s--) {
            for (int i = 0; i < n; i++) {
                Arrays.fill(g[i], Integer.MAX_VALUE / 2);
                g[i][i] = 0;
            }
            for (int[] r : roads) {
                int u = r[0], v = r[1], w = r[2];
                if ((s >> u & 1) != 0 && (s >> v & 1) != 0) {
                    g[u][v] = Math.min(g[u][v], w);
                    g[v][u] = Math.min(g[v][u], w);
                }
            }
            for (int k = 0; k < n; k++) {
                for (int i = 0; i < n; i++) {
                    for (int j = 0; j < n; j++) {
                        g[i][j] = Math.min(g[i][j], g[i][k] + g[k][j]);
                    }
                }
            }
            int max = 0;
            for (int u = 0; u < n; u++) {
                for (int v = 0; v < n; v++) {
                    if ((s >> u & 1) != 0 && (s >> v & 1) != 0) {
                        max = Math.max(max, g[u][v]);
                    }
                }
            }
            if (max <= maxDistance) ans++;
        }
        return ans;
    }
}

你可能感兴趣的:(算法学习,leetcode,java,算法)