0
点赞
收藏
分享

微信扫一扫

【高效开发工具系列】语雀Excel入门

75. 颜色分类,76. 最小覆盖子串,77. 组合,每题做详细思路梳理,配套Python&Java双语代码, 2024.03.21 可通过leetcode所有测试用例。

目录

75. 颜色分类

解题思路

完整代码

Python

Java

76. 最小覆盖子串

解题思路

完整代码

Python

Java

77. 组合

解题思路

完整代码

Python

Java


75. 颜色分类

解题思路

其核心思想是使用三个指针来分别跟踪 0、1 和 2。我们可以将数组中的元素分为三部分:红色区(0),白色区(1),以及蓝色区(2)。以下是具体的步骤:

  1. 初始化三个指针lowmidhighlow 指针跟踪红色区的最后一个元素的下一个位置,mid 指针用于遍历整个数组,high 指针跟踪蓝色区的第一个元素的前一个位置。初始时,lowmid 都设置为数组的起始位置,high 设置为数组的末尾位置。

  2. 遍历数组:当 mid 指针小于等于 high 指针时,进行遍历:

    • 如果 nums[mid] 等于 0(红色),则将其与 nums[low] 交换,并将 lowmid 指针都向前移动一位。
    • 如果 nums[mid] 等于 1(白色),则不需要交换,只需将 mid 指针向前移动一位。
    • 如果 nums[mid] 等于 2(蓝色),则将其与 nums[high] 交换,并将 high 指针向后移动一位。此时不移动 mid 指针,因为交换后的元素还未被检查。
  3. 重复步骤 2,直到 mid 指针超过 high 指针。

完整代码

Python
class Solution:
    def sortColors(self, nums: List[int]) -> None:
        low, mid, high = 0, 0, len(nums) - 1

        while mid <= high:
            if nums[mid] == 0:
                nums[low], nums[mid] = nums[mid], nums[low]
                low += 1
                mid += 1
            elif nums[mid] == 1:
                mid += 1
            else:
                nums[mid], nums[high] = nums[high], nums[mid]
                high -= 1
Java
class Solution {
    public void sortColors(int[] nums) {
        int low = 0, mid = 0, high = nums.length - 1;

        while (mid <= high) {
            switch (nums[mid]) {
                case 0:
                    // 交换 low 和 mid 的值
                    int temp = nums[low];
                    nums[low] = nums[mid];
                    nums[mid] = temp;
                    low++;
                    mid++;
                    break;
                case 1:
                    mid++;
                    break;
                case 2:
                    // 交换 mid 和 high 的值
                    temp = nums[mid];
                    nums[mid] = nums[high];
                    nums[high] = temp;
                    high--;
                    break;
            }
        }
    }
}

76. 最小覆盖子串

解题思路

我们可以使用滑动窗口的方法。基本思想是使用两个指针 leftright 来表示 s 中的一个窗口,并在这个窗口中寻找包含 t 所有字符的最小子串。这个过程分为几个步骤:

  1. 初始化:创建两个哈希表,一个用于存储字符串 t 中字符的频率(称为 need),另一个用于存储当前窗口中字符的频率(称为 window)。还需要两个指针 leftright 表示当前窗口的左右边界,初始化为 0。定义 valid 变量来记录窗口中满足 need 条件的字符数量。

  2. 扩大窗口:移动右指针 right 扩大窗口,直到窗口中包含了 t 的所有字符。

  3. 更新结果:当窗口包含了 t 的所有字符后,尝试移动左指针 left 缩小窗口,同时更新最小子串的长度和起始位置。如果当前窗口的长度小于之前找到的最小子串长度,更新最小子串长度和起始位置。

  4. 缩小窗口:继续移动左指针 left 缩小窗口,直到窗口不再满足 t 的所有字符。此时再次扩大窗口,重复步骤 2 和 3。

  5. 返回结果:根据记录的最小子串起始位置和长度返回最终结果。

完整代码

Python
class Solution:
    def minWindow(self, s: str, t: str) -> str:
        from collections import Counter
        need, window = Counter(t), {}
        left = right = 0
        valid = 0
        start, length = 0, float('inf')
        
        while right < len(s):
            # c 是将移入窗口的字符
            c = s[right]
            # 右移窗口
            right += 1
            # 进行窗口内数据的一系列更新
            if c in need:
                window[c] = window.get(c, 0) + 1
                if window[c] == need[c]:
                    valid += 1
            
            # 判断左侧窗口是否要收缩
            while valid == len(need):
                # 更新最小覆盖子串
                if right - left < length:
                    start = left
                    length = right - left
                # d 是将移出窗口的字符
                d = s[left]
                # 左移窗口
                left += 1
                # 进行窗口内数据的一系列更新
                if d in need:
                    if window[d] == need[d]:
                        valid -= 1
                    window[d] -= 1
        
        return "" if length == float('inf') else s[start:start+length]
Java
class Solution {
    public String minWindow(String s, String t) {
        HashMap<Character, Integer> need = new HashMap<>();
        HashMap<Character, Integer> window = new HashMap<>();
        for (char c : t.toCharArray()) need.put(c, need.getOrDefault(c, 0) + 1);

        int left = 0, right = 0;
        int valid = 0;
        int start = 0, length = Integer.MAX_VALUE;
        
        while (right < s.length()) {
            char c = s.charAt(right);
            right++;
            if (need.containsKey(c)) {
                window.put(c, window.getOrDefault(c, 0) + 1);
                if (window.get(c).equals(need.get(c))) valid++;
            }

            while (valid == need.size()) {
                if (right - left < length) {
                    start = left;
                    length = right - left;
                }
                char d = s.charAt(left);
                left++;
                if (need.containsKey(d)) {
                    if (window.get(d).equals(need.get(d))) valid--;
                    window.put(d, window.get(d) - 1);
                }
            }
        }
        
        return length == Integer.MAX_VALUE ? "" : s.substring(start, start + length);
    }
}

 

77. 组合

解题思路

我们可以使用回溯法,这是一种通过探索所有可能的候选解来找出所有解的解决方案的算法。当搜索到一个可能解时,回溯法会先记录下这个解,然后撤销到上一步状态,尝试另一种选择,继续探索直到所有的选择都尝试过了。以下是具体的步骤:

  1. 定义回溯函数:创建一个回溯函数 backtrack,它接受当前的组合 combination 和下一个要添加到组合中的数字 start

  2. 递归的终止条件:当 combination 的长度等于 k 时,将其添加到结果列表中,然后返回。

  3. 遍历所有可能的选择:从 startn 遍历所有可能的数字。对于每一个数字,将其添加到当前组合中,然后递归地调用 backtrack 函数进入下一层。

  4. 回溯:递归调用返回后,撤销上一步的操作,即从 combination 中移除上一步添加的数字,尝试下一个可能的数字。

  5. 调用回溯函数并返回结果:初始化一个空列表来存储所有可能的组合,然后从数字 1 开始调用回溯函数。

完整代码

Python
class Solution:
    def combine(self, n: int, k: int) -> List[List[int]]:
        result = []
        combination = []

        def backtrack(start):
            if len(combination) == k:
                result.append(combination[:])
                return
            for i in range(start, n + 1):
                combination.append(i)
                backtrack(i + 1)
                combination.pop()

        backtrack(1)
        return result
Java
class Solution {
    public List<List<Integer>> combine(int n, int k) {
        List<List<Integer>> result = new ArrayList<>();
        List<Integer> combination = new ArrayList<>();

        void backtrack(int start) {
            if (combination.size() == k) {
                result.add(new ArrayList<>(combination));
                return;
            }
            for (int i = start; i <= n; i++) {
                combination.add(i);
                backtrack(i + 1);
                combination.remove(combination.size() - 1);
            }
        }

        backtrack(1);
        return result;
    }
}
举报

相关推荐

0 条评论