LeetCode-23day:技巧经典
技巧经典题目总结(C++实现)
技巧在算法中扮演着重要的角色,能够帮助我们以更高效的方式解决问题。本文总结了五道经典的技巧问题,帮助你更好地理解和掌握这些技巧的应用。
🟢 1. 只出现一次的数字(Single Number)
📄 题目描述:
给定一个非空整数数组 nums
,其中除了一个数字外,其余每个数字都出现了两次。找到那个只出现一次的数字。
🧠 解题思路(简洁版)
- 位运算:
- 使用异或运算的性质:相同数字异或结果为 0,0 与任何数字异或结果为该数字。
- 遍历数组,所有数字异或的结果即为只出现一次的数字。
⏱️ 复杂度分析
- 时间复杂度:
O(n)
,其中n
为数组长度。 - 空间复杂度:
O(1)
。
✅ C++ 实现
class Solution {
public:int singleNumber(vector<int>& nums) {int ret = 0;for (auto e : nums) ret ^= e;return ret;}
};
🟢 2. 多数元素(Majority Element)
📄 题目描述:
给定一个大小为 n
的数组 nums
,其中多数元素是指出现次数大于 ⌊ n/2 ⌋
的元素。假设数组非空且多数元素总是存在,找到这个多数元素。
🧠 解题思路(简洁版)
- 排序法:
- 对数组进行排序。
- 返回中间位置的元素,因为多数元素一定占据中间位置。
⏱️ 复杂度分析
- 时间复杂度:
O(n log n)
,排序的时间复杂度。 - 空间复杂度:
O(1)
或O(n)
,取决于排序算法的实现。
✅ C++ 实现
class Solution {
public:int majorityElement(vector<int>& nums) {sort(nums.begin(), nums.end());return nums[nums.size() / 2];}
};
🟢 3. 颜色分类(Sort Colors)
📄 题目描述:
给定一个包含红色、白色和蓝色的数组 nums
,将它们按照红色、白色、蓝色的顺序排序。这里使用整数 0、1 和 2 分别表示红色、白色和蓝色。
🧠 解题思路(简洁版)
- 两次遍历:
- 第一次遍历,将所有 0 移到前面。
- 第二次遍历,从上次停止的位置开始,将所有 1 移到前面。
⏱️ 复杂度分析
- 时间复杂度:
O(n)
,其中n
为数组长度。 - 空间复杂度:
O(1)
。
✅ C++ 实现
class Solution {
public:void sortColors(vector<int>& nums) {int n = nums.size();int ptr = 0;for (int i = 0; i < n; i++) {if (nums[i] == 0) {swap(nums[i], nums[ptr]);++ptr;}}for (int i = ptr; i < n; i++) {if (nums[i] == 1) {swap(nums[i], nums[ptr]);++ptr;}}}
};
🟢 4. 下一个排列(Next Permutation)
📄 题目描述:
给定一个整数数组 nums
,重新排列数组元素,使其下一个字典序更大的排列。如果不存在下一个更大的排列,则将数组重新排列成最小的排列(即升序排列)。
🧠 解题思路(简洁版)
- 寻找下一个排列:
- 从右向左找到第一个升序对
(i, i+1)
。 - 若找到,从右向左找到第一个大于
nums[i]
的数nums[j]
,交换nums[i]
和nums[j]
。 - 反转
i+1
到末尾的部分,使其最小。
- 从右向左找到第一个升序对
⏱️ 复杂度分析
- 时间复杂度:
O(n)
,其中n
为数组长度。 - 空间复杂度:
O(1)
。
✅ C++ 实现
class Solution {
public:void nextPermutation(vector<int>& nums) {int i = nums.size() - 2;while (i >= 0 && nums[i] >= nums[i + 1]) {i--;}if (i >= 0) {int j = nums.size() - 1;while (j >= 0 && nums[i] >= nums[j]) {j--;}swap(nums[i], nums[j]);}reverse(nums.begin() + i + 1, nums.end());}
};
🟢 5. 寻找重复数(Find the Duplicate Number)
📄 题目描述:
给定一个包含 n + 1
个整数的数组 nums
,其中每个整数都在 1 到 n
(含)之间。假设数组中只有一个重复的数字,找到这个重复的数字。
🧠 解题思路(简洁版)
- 快慢指针:
- 使用 Floyd 判圈算法。
- 第一次相遇后,将一个指针重置到起点,再次相遇点即为重复元素。
⏱️ 复杂度分析
- 时间复杂度:
O(n)
,其中n
为数组长度。 - 空间复杂度:
O(1)
。
✅ C++ 实现
class Solution {
public:int findDuplicate(vector<int>& nums) {int slow = 0, fast = 0;do {slow = nums[slow];fast = nums[nums[fast]];} while (slow != fast);slow = 0;while (slow != fast) {slow = nums[slow];fast = nums[fast];}return slow;}
};
📌 总结
题目 | 方法 | 时间复杂度 | 空间复杂度 |
---|---|---|---|
只出现一次的数字 | 位运算 | O(n) | O(1) |
多数元素 | 排序法 | O(n log n) | O(1) 或 O(n) |
颜色分类 | 两次遍历 | O(n) | O(1) |
下一个排列 | 寻找下一个排列 | O(n) | O(1) |
寻找重复数 | 快慢指针 | O(n) | O(1) |
希望本文对你有所帮助!如果你还有其他问题,欢迎继续提问。