🧠 1. 只出现一次的数字
🧩 题目描述
给定一个 非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出这个只出现一次的元素。
要求:
- 时间复杂度:O(n)
- 空间复杂度:O(1)
✅ 解题思路
利用异或运算的性质:
a ^ a = 0a ^ 0 = a
所有数字都出现两次,异或后都变成 0,剩下的就是只出现一次的那个数字。
📌 举个例子:
2 ^ 3 ^ 3 = 2 (3 ^ 3 = 0, 2 ^ 0 = 2)
💻 C++ 实现
class Solution {
public:
int singleNumber(vector<int>& nums) {
int res = 0;
for (auto num : nums) {
res ^= num;
}
return res;
}
};
🗳️ 2. 多数元素
🧩 题目描述
给定一个大小为 n 的数组,返回其中的多数元素(即出现次数 > ⌊n/2⌋)。
保证多数元素一定存在。
✅ 解题思路:摩尔投票法
- 候选人初始为空,票数为 0;
- 每遇到相同的数字票数 +1,不同的数字票数 -1;
- 票数为 0 时更换候选人;
- 最终留下的候选人就是多数元素。
💻 C++ 实现
class Solution {
public:
int majorityElement(vector<int>& nums) {
int x = 0, y = 0;
for(int i = 0; i < nums.size(); i++){
if(nums[i] == nums[x]) y++;
else y--;
if(y == 0){ x = i; y = 1;}
}
return nums[x];
}
};
🎨 3. 颜色分类
🧩 题目描述
将包含 0(红色)、1(白色)、2(蓝色)的数组排序,不能使用内置排序函数。
✅ 解题思路:双指针(三路快排思想)
-
左指针放置 0,右指针放置 2;
-
遍历数组时遇到:
0:与左指针交换,左指针右移;2:与右指针交换,右指针左移;1:跳过。
💻 C++ 实现
class Solution {
public:
void sortColors(vector<int>& nums) {
int l = 0, r = nums.size()-1;
for(int i = 0; i < nums.size(); i++){
while(nums[i] == 2 && i < r){
swap(nums[i], nums[r--]);
}
if(nums[i] == 0){
swap(nums[i], nums[l++]);
}
}
}
};
🔢 4. 下一个排列
🧩 题目描述
给定一个整数数组 nums,找出其下一个字典序排列。要求 就地修改,使用常数级空间。
✅ 解题思路
- 从后往前找到第一个递增的位置
i; - 再从后向前找到第一个比
nums[i]大的元素j; - 交换
nums[i]和nums[j]; - 反转
i+1到末尾这段子数组。
📌 举例:
从后往前找第一个逆序的位置
- 如果找不到则当前排列就是最大的,只需要全部翻转成为升序即可
- 如果存在这个位置 如 [1 2 3 5 4 2 1], 3 就是找到的位置,将 3 和第一个大于 3 的值进行替换
更换后:[1 2 4 5 3 2 1],这样 4 后面的子数组一定就是逆序数组,将其翻转成升序即可得到
答案:[1 2 4 1 2 3 5]
💻 C++ 实现
class Solution {
public:
void nextPermutation(vector<int>& nums) {
int l = -1;
for(int i = nums.size()-1; i >= 1; i--){
if(nums[i] > nums[i-1]){l = i-1; break;}
}
if(l == -1){
reverse(nums.begin(), nums.end());
return;
}
int r;
for(int i = nums.size()-1;i >= l; i--){
if(nums[i] > nums[l]){r = i; break;}
}
swap(nums[l], nums[r]);
reverse(nums.begin() + l + 1, nums.end());
}
};
🔍 5. 寻找重复数
🧩 题目描述
一个长度为 n+1 的数组,所有数在 [1,n] 范围内,只有一个重复数字,不能修改数组,空间复杂度 O(1)。
✅ 解题思路:快慢指针(Floyd 判圈)
视索引和值为链表的节点和指针,用快慢指针找环入口:
- 慢指针每次走一步,快指针走两步;
- 相遇后,将慢指针重置为起点;
- 再次相遇处就是重复数字。
💻 C++ 实现
class Solution {
public:
int findDuplicate(vector<int>& nums) {
int slow=0, fast=0;
while(1){
slow = nums[slow];
r = nums[nums[fast]];
if(slow == fast)break;
}
slow = 0;
while(slow != fast){
slow = nums[slow];
fast = nums[fast];
}
return slow;
}
};