leetcode hot100 技巧

如有缺漏谬误,还请批评指正。

1.只出现一次的数字

       利用异或运算相同得0的特点。所有出现过两次的数字都会在异或运算累加过程中被抵消。

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int res=0;
        for(int i=0;i<nums.size();i++) res^=nums[i];
        return res;
    }
};

2.多数元素

        随机取数,然后判断是否是答案。因为众数被选中的概率大于50%,所以时间复杂度虽然理论上可能出现O(∞)的情况,但实际上可以达到O(n)。

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        while(true){
            int candidate=nums[rand()%nums.size()];
            int count=0;
            for(int i=0;i<nums.size();i++){
                if(nums[i]==candidate){
                    count++;
                    if (count>nums.size()/2) return candidate;
                }
            }
        }
        return -1;
    }
};

3.颜色分类

        经典的“荷兰国旗”问题。

(1)单指针解法

class Solution {
public:
    void sortColors(vector<int>& nums) {
        int i=0;
        for(int j=0;j<nums.size();j++){
            if(nums[j]==0){
                swap(nums[i],nums[j]);
                i++;
            }
        }
        for(int j=i;j<nums.size();j++){
            if(nums[j]==1){
                swap(nums[i],nums[j]);
                i++;
            }
        }
    }
};

(2)双指针解法

        比单指针少了一趟遍历。

①两个同向指针分别记录0的交换位置和1的交换位置。

class Solution {
public:
    void sortColors(vector<int>& nums) {
        int n=nums.size();
        int ptr0=0,ptr1=0;
        for(int i=0;i<n;i++){
            if(nums[i]==0){
                swap(nums[i],nums[ptr0++]);
                if(ptr1<ptr0) ptr1++;
            }
            if(nums[i]==1) swap(nums[i],nums[ptr1++]);
        }
    }
};

②左右指针分别记录0的交换位置和2的交换位置。 

class Solution {
public:
    void sortColors(vector<int>& nums) {
        int n = nums.size();
        int r0=0,l2=n-1;  // r0: 0的右边界,l2:2的左边界
        for(int i=0;i<=l2;i++){       // 必须包含等于,因为nums[r]可能还没处理
            if(nums[i]==0) swap(nums[i],nums[r0++]);  // 0交换到左边,r0右移
            //换完后的理想状态:换过后nums[i]是1(1处在0的右边界和2的左边界之间)
            else if(nums[i]==2){
                swap(nums[i],nums[l2--]);  // 2交换到右边,l2左移
                if(nums[i]!=1) i--;  
                //num[i]==0的情况:2和0换,换过后的0需再换一遍到左边界
                //num[i]==2的情况:2和2换,换过后的2需重新处理
            }
        }
    }
};

4.下一个排列

三个关键步骤:

  • 找到 i:i是第一个破坏从后向前升序的位置,这意味着nums[i]可以增大以得到更大的排列。

  • 找到 jnums[j] 是 i 之后比 nums[i] 大的最小数,交换后 nums[i]增大,但 i 之后的部分仍然降序。

  • 反转:反转 i+1之后的部分使其升序,这样这部分最小,确保了整个排列是“下一个”排列。

class Solution {
public:
    void nextPermutation(vector<int>& nums) {
        int n=nums.size();
        int i=n-2;
        // 1. 找到第一个不符合逆序升的nums[i]
        while(i>=0&&nums[i]>=nums[i+1]) i--;
        // 2. 再找第一个比nums[i]大的nums[j],swap两个数
        if(i>=0){
            int j=n-1;
            while(j>=0&&nums[j]<=nums[i]) j--;
            swap(nums[i], nums[j]);
        }
        // 3.反转 i+1 到末尾的部分(使其升序)
        reverse(nums.begin()+i+1, nums.end());
    }
};

5.多数问题

核心思想:将数组视为链表,并利用快慢指针检测环。

相遇的地点是环的入口(即重复数字):推导如下。

class Solution {
public:
    int findDuplicate(vector<int>& nums) {
        // 初始化快慢指针,初始位置在数组的起始位置(索引0)
        int slow=0,fast=0;
        // 第一阶段:检测环的存在(Floyd's Tortoise and Hare算法)
        do{
            slow=nums[slow];       // 慢指针每次移动一步
            fast=nums[nums[fast]]; // 快指针每次移动两步
        } while (slow!=fast);      // 当快慢指针相遇时,说明存在环
        // 第二阶段:找到环的入口(即重复的数字)
        slow=0; // 将慢指针重置到起点
        while(slow!=fast){
            slow=nums[slow]; // 慢指针每次移动一步
            fast=nums[fast]; // 快指针每次移动一步
        }
        // 最终相遇点就是重复的数字
        return slow;
    }
};

 

 

### LeetCode Hot 100 Problems 列表 LeetCode 的热门题目列表通常由社区投票选出,涵盖了各种难度级别的经典编程挑战。这些题目对于准备技术面试非常有帮助。以下是部分 LeetCode 热门 100 题目列表: #### 数组与字符串 1. **两数之和 (Two Sum)** 2. **三数之和 (3Sum)** 3. **无重复字符的最长子串 (Longest Substring Without Repeating Characters)** 4. **寻找两个正序数组的中位数 (Median of Two Sorted Arrays)** #### 动态规划 5. **爬楼梯 (Climbing Stairs)** 6. **不同的二叉搜索树 (Unique Binary Search Trees)** 7. **最大子序列和 (Maximum Subarray)** #### 字符串处理 8. **有效的括号 (Valid Parentheses)** 9. **最小覆盖子串 (Minimum Window Substring)** 10. **字母异位词分组 (Group Anagrams)** #### 图论 11. **岛屿数量 (Number of Islands)** 12. **课程表 II (Course Schedule II)** #### 排序与查找 13. **最接近原点的 K 个点 (K Closest Points to Origin)** 14. **接雨水 (Trapping Rain Water)** 15. **最长连续序列 (Longest Consecutive Sequence)[^2]** #### 堆栈与队列 16. **每日温度 (Daily Temperatures)** 17. **滑动窗口最大值 (Sliding Window Maximum)** #### 树结构 18. **验证二叉搜索树 (Validate Binary Search Tree)** 19. **二叉树的最大路径和 (Binary Tree Maximum Path Sum)** 20. **从前序与中序遍历序列构造二叉树 (Construct Binary Tree from Preorder and Inorder Traversal)** #### 并查集 21. **冗余连接 II (Redundant Connection II)** #### 贪心算法 22. **跳跃游戏 (Jump Game)** 23. **分割等和子集 (Partition Equal Subset Sum)** #### 双指针技巧 24. **环形链表 II (Linked List Cycle II)[^1]** 25. **相交链表 (Intersection of Two Linked Lists)** #### 其他重要题目 26. **LRU缓存机制 (LRU Cache)** 27. **打家劫舍系列 (House Robber I & II)** 28. **编辑距离 (Edit Distance)** 29. **单词拆分 (Word Break)** 此列表并非官方发布版本而是基于社区反馈整理而成。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值