目录

力扣热题-100技巧专题经典题解析

力扣热题 100:技巧专题经典题解析

系列文章目录

在力扣(LeetCode)平台上,有一些题目需要特定的技巧来解决。今天,我们就来详细解析技巧专题中的几道经典题目,帮助大家更好地理解解题思路和技巧。

一、只出现一次的数字(题目 136)

1. 题目描述

给定一个非空整数数组,其中除了一个元素只出现一次外,其他元素都出现两次。找到那个只出现一次的元素。

2. 示例

示例 1:

输入: nums = [2, 2, 1]

输出: 1

3. 解题思路

这道题主要考察位运算的应用。我们可以使用异或运算来找到只出现一次的数字。异或运算的性质是:一个数异或自己为 0,一个数异或 0 为自己。因此,遍历数组,将所有元素异或在一起,最终结果就是只出现一次的数字。

4. 代码实现(Java)

public class Solution {
    public int singleNumber(int[] nums) {
        int result = 0;
        for (int num : nums) {
            result ^= num;
        }
        return result;
    }
}

5. 复杂度分析

  • 时间复杂度 :O(n),其中 n 是数组的长度。需要遍历数组一次。
  • 空间复杂度 :O(1),只使用了常数级别的额外空间。

二、多数元素(题目 169)

1. 题目描述

给定一个大小为 n 的数组,找到出现次数大于 ⌊ n/2 ⌋ 的元素。

2. 示例

示例 1:

输入: nums = [3, 2, 3]

输出: 3

3. 解题思路

这道题主要考察 Boyer-Moore 投票算法的应用。我们可以维护一个候选元素和其计数,遍历数组,如果当前元素与候选元素相同,则计数加 1,否则计数减 1。当计数为 0 时,更新候选元素为当前元素。

4. 代码实现(Java)

public class Solution {
    public int majorityElement(int[] nums) {
        int candidate = nums[0];
        int count = 1;
        for (int i = 1; i < nums.length; i++) {
            if (nums[i] == candidate) {
                count++;
            } else {
                count--;
                if (count == 0) {
                    candidate = nums[i];
                    count = 1;
                }
            }
        }
        return candidate;
    }
}

5. 复杂度分析

  • 时间复杂度 :O(n),其中 n 是数组的长度。需要遍历数组一次。
  • 空间复杂度 :O(1),只使用了常数级别的额外空间。

三、颜色分类(题目 75)

1. 题目描述

给定一个包含红色、白色和蓝色的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色的顺序排列。用 0、1 和 2 分别表示红色、白色和蓝色。

2. 示例

示例 1:

输入: nums = [2, 0, 2, 1, 1, 0]

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

3. 解题思路

这道题主要考察三指针的应用。我们可以使用三个指针,分别指向当前红色、白色和蓝色的位置。遍历数组,根据元素的值交换到相应的位置。

4. 代码实现(Java)

public class Solution {
    public void sortColors(int[] nums) {
        int red = 0, white = 0, blue = nums.length - 1;
        while (white <= blue) {
            if (nums[white] == 0) {
                swap(nums, red, white);
                red++;
                white++;
            } else if (nums[white] == 1) {
                white++;
            } else {
                swap(nums, white, blue);
                blue--;
            }
        }
    }

    private void swap(int[] nums, int i, int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
}

5. 复杂度分析

  • 时间复杂度 :O(n),其中 n 是数组的长度。需要遍历数组一次。
  • 空间复杂度 :O(1),只使用了常数级别的额外空间。

四、下一个排列(题目 31)

1. 题目描述

给定一个整数数组,重新排列成字典序的下一个排列。如果不存在下一个排列,则重新排列成最低的排列。

2. 示例

示例 1:

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

输出: [1, 3, 2]

3. 解题思路

这道题主要考察数组的操作和排列的生成。我们可以按照以下步骤生成下一个排列:

  1. 从后向前找到第一个可以增大的数。
  2. 从后向前找到第一个比该数大的数,并交换。
  3. 将该数后面的部分反转,使其最小。

4. 代码实现(Java)

public class Solution {
    public void nextPermutation(int[] nums) {
        int i = nums.length - 2;
        while (i >= 0 && nums[i] >= nums[i + 1]) {
            i--;
        }
        if (i >= 0) {
            int j = nums.length - 1;
            while (j >= 0 && nums[j] <= nums[i]) {
                j--;
            }
            swap(nums, i, j);
        }
        reverse(nums, i + 1, nums.length - 1);
    }

    private void swap(int[] nums, int i, int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }

    private void reverse(int[] nums, int start, int end) {
        while (start < end) {
            swap(nums, start, end);
            start++;
            end--;
        }
    }
}

5. 复杂度分析

  • 时间复杂度 :O(n),其中 n 是数组的长度。需要遍历数组多次,但每次操作都是线性时间。
  • 空间复杂度 :O(1),只使用了常数级别的额外空间。

五、寻找重复数(题目 287)

1. 题目描述

给定一个包含 n + 1 个整数的数组,其中每个元素在 1 到 n 之间,至少存在一个重复元素。找到那个重复的元素。

2. 示例

示例 1:

输入: nums = [1, 3, 4, 2, 2]

输出: 2

3. 解题思路

这道题主要考察二分查找的应用。我们可以使用二分查找来确定重复元素。具体步骤如下:

  1. 初始化左右边界为 1 和 n。
  2. 计算中间值 mid,统计数组中小于等于 mid 的元素个数。
  3. 如果个数大于 mid,则重复元素在左半部分,否则在右半部分。
  4. 重复步骤 2 和 3,直到找到重复元素。

4. 代码实现(Java)

public class Solution {
    public int findDuplicate(int[] nums) {
        int left = 1, right = nums.length - 1;
        while (left < right) {
            int mid = left + (right - left) / 2;
            int count = 0;
            for (int num : nums) {
                if (num <= mid) {
                    count++;
                }
            }
            if (count > mid) {
                right = mid;
            } else {
                left = mid + 1;
            }
        }
        return left;
    }
}

5. 复杂度分析

  • 时间复杂度 :O(n log n),其中 n 是数组的长度。二分查找的时间复杂度为 O(log n),每次统计个数的时间复杂度为 O(n)。
  • 空间复杂度 :O(1),只使用了常数级别的额外空间。

以上就是力扣热题 100 中与技巧相关的经典题目的详细解析,希望对大家有所帮助。在实际刷题过程中,建议大家多动手实践,理解解题思路的本质,这样才能更好地应对各种算法问题。 https://i-blog.csdnimg.cn/direct/f496664cf7fd4a06877a9ebe9e61e76f.png#pic_center