hot 100 技巧题

技巧

只出现一次的数字

任何数与自身异或结果为 0:即 a ^ a = 0;

任何数与 0 异或结果为自身:即 a ^ 0 = a。

给你一个 非空 整数数组 nums ,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。

cpp 复制代码
class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int ans = nums[0];
        if(nums.size() > 1) {
            for(int i = 1; i < nums.size(); i++) {
                ans = ans ^ nums[i];
            }
        }
        return ans;
    }
};

多数元素

给定一个大小为 n 的数组 nums ,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。

你可以假设数组是非空的,并且给定的数组总是存在多数元素。

采用了摩尔投票算法(Boyer-Moore Majority Vote-counting algorithm) 来求解 "多数元素" 问题,核心思路是通过 "抵消" 不同元素的票数,最终多数元素(出现次数超过一半的元素)最终会被保留下来。
具体步骤:

维护两个变量:x(当前候选的多数元素)和 vote(候选元素的票数)。

遍历数组中的每个元素 num:

若 vote == 0(当前没有候选元素),则将 num 设为新的候选元素 x = num。

若 num == x(当前元素与候选元素相同),则票数 vote += 1(支持)。

若 num != x(当前元素与候选元素不同),则票数 vote -= 1(抵消)。

遍历结束后,x 就是多数元素。

cpp 复制代码
class Solution {
public:
    int majorityElement(vector<int>& nums) {
        int x = 0, vote = 0;
        for(int num : nums) {
            if(vote == 0) {
                x = num;
            }
            vote += (x == num) ? 1 : -1;
        }
        return x;
    }
};

颜色分类

给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums ,原地 对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。

我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。

必须在不使用库内置的 sort 函数的情况下解决这个问题。

核心思路

通过两个指针 p0 和 p1 划分区间,遍历数组时将 0 和 1 交换到正确的位置:

p0:指向 "下一个 0 应该存放的位置"(p0 左侧全是 0)。

p1:指向 "下一个 1 应该存放的位置"(p0 到 p1-1 之间全是 1)。

遍历到 i 时,i 右侧是待处理的元素,最终 p1 右侧全是 2。

分步拆解逻辑

初始化指针:p0 = 0,p1 = 0(初始时无 0 和 1,指针都在起点)。

遍历数组,对每个元素 nums[i] 处理:

情况 1:nums[i] == 1直接将 nums[i] 交换到 p1 指向的位置(因为 p1 是下一个 1 的存放处),然后 p1++(1 的区间向右扩展)。例:[0,1,1,2] 中,i=2 是 1,交换后 p1 从 1 变为 2。

情况 2:nums[i] == 0第一步:将 nums[i] 交换到 p0 指向的位置(0 的存放处),此时 p0 处可能原本是 1(因为 p0 <= p1,p0 到 p1 之间是 1)。第二步:如果 p0 < p1(说明刚才交换走的是 1),需要把这个 1 交换到 p1 指向的位置(保证 1 的区间正确)。第三步:p0++ 和 p1++(0 和 1 的区间都向右扩展)。例:[1,0,2] 中,i=1 是 0:

先交换 nums[1] 和 nums[0] → [0,1,2];

因 p0=0 < p1=1,无需二次交换;

p0 和 p1 都变为 1 和 2。

情况 3:nums[i] == 2无需处理,因为遍历结束后 p1 右侧自然都是 2。

cpp 复制代码
class Solution {
public:
    void sortColors(vector<int>& nums) {
        int n = nums.size();
        int p0 = 0, p1 = 0;
        for(int i = 0; i < n; i++) {
            if(nums[i] == 1){
                swap(nums[i], nums[p1]);
                ++p1;
            }
            else if(nums[i] == 0){
                swap(nums[i],nums[p0]);
                if(p0 < p1){
                    swap(nums[i], nums[p1]);
                }
                p0++;
                p1++;
            }
        }
    }
};

下一个排列

整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。

例如,arr = [1,2,3] ,以下这些都可以视作 arr 的排列:[1,2,3]、[1,3,2]、[3,1,2]、[2,3,1] 。

整数数组的 下一个排列 是指其整数的下一个字典序更大的排列。更正式地,如果数组的所有排列根据其字典顺序从小到大排列在一个容器中,那么数组的 下一个排列 就是在这个有序容器中排在它后面的那个排列。如果不存在下一个更大的排列,那么这个数组必须重排为字典序最小的排列(即,其元素按升序排列)。

例如,arr = [1,2,3] 的下一个排列是 [1,3,2] 。

类似地,arr = [2,3,1] 的下一个排列是 [3,1,2] 。

而 arr = [3,2,1] 的下一个排列是 [1,2,3] ,因为 [3,2,1] 不存在一个字典序更大的排列。

给你一个整数数组 nums ,找出 nums 的下一个排列。

必须 原地 修改,只允许使用额外常数空间。

cpp 复制代码
class Solution {
public:
    void nextPermutation(vector<int>& nums) {
        int n = nums.size();
        int i = n - 2;
        while(i >= 0 && nums[i] >= nums[i+1]) {
            i--;
        }
        if(i >= 0) {
            int j = n - 1;
            while(nums[j] <= nums[i]){
                j--;
            }
            swap(nums[i], nums[j]);
        }
        reverse(nums.begin() + i + 1, nums.end());
    }
};

寻找重复数

给定一个包含 n + 1 个整数的数组 nums ,其数字都在 [1, n] 范围内(包括 1 和 n),可知至少存在一个重复的整数。

假设 nums 只有 一个重复的整数 ,返回 这个重复的数 。

你设计的解决方案必须 不修改 数组 nums 且只用常量级 O(1) 的额外空间。

cpp 复制代码
class Solution {
public:
    int findDuplicate(vector<int>& nums) {
        int tmp;
        sort(nums.begin(), nums.end());
        for(int i = 0; i < nums.size() - 1; i++) {
            tmp = nums[i+1] - nums[i];
            if(tmp == 0) return nums[i];
        }
        return -1;
    }
};
相关推荐
暴风鱼划水3 小时前
卡码网语言基础课(Python) | 19.洗盘子
python·算法
会编程是什么感觉...3 小时前
算法 - PEC校验
单片机·算法
再卷也是菜4 小时前
算法基础篇(8)贪心算法
算法·贪心算法·1024程序员节
AI科技星4 小时前
接近光速运动下的光速不变性:基于张祥前统一场论的推导与验证
数据结构·人工智能·经验分享·算法·计算机视觉
陈苏同学5 小时前
笔记1.4:机器人学的语言——三维空间位姿描述 (旋转矩阵 - 齐次变换矩阵 - 欧拉角 - 四元数高效表示旋转)
笔记·线性代数·算法·机器人
scx201310045 小时前
20251025 分治总结
数据结构·c++·算法
碧海银沙音频科技研究院5 小时前
DiVE长尾识别的虚拟实例蒸馏方法
arm开发·人工智能·深度学习·算法·音视频
居7然7 小时前
DeepSeek OCR:重新定义AI文档处理的“降本增效”新范式
人工智能·算法·语言模型·自然语言处理·大模型·ocr
while(1){yan}7 小时前
数据结构之堆
数据结构·python·算法