Hot100——普通数组

53最大子数字

思路

  1. 核心思想:

    • 遍历数组时,持续维护一个当前子数组的和(now)
    • 同时记录遍历过程中遇到的最大子数组和(ans)
  2. 具体逻辑:

    • 初始化 now 为 0(当前子数组和),ans 为一个极小值(-1e9,确保能覆盖所有可能的负值情况)
    • 遍历数组中的每个元素:
      • 将当前元素加入 now(扩展当前子数组)
      • 用 now 更新 ans(保留最大值)
      • 如果 now 小于 0,说明当前子数组的和为负,继续保留会拖累后续结果,因此重置 now 为 0(相当于重新开始一个新的子数组)
  3. 适用场景:

    • 解决 "最大子序和" 问题,即从整数数组中找出一个具有最大和的连续子数组
    • 能高效处理包含负数的数组,例如 [-2,1,-3,4,-1,2,1,-5,4] 这样的输入,会正确返回 6(对应子数组 [4,-1,2,1])

这个算法的优势在于只需要一次遍历就能得到结果,是解决此类问题的最优方案之一。

代码

复制代码
class Solution {
public:
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
        sort(intervals.begin(),intervals.end(),[](const vector<int> &a,const vector<int> &b)
        {
            if(a[0]!=b[0])
            {
                return a[0]<b[0];
            }
            return a[1]<b[1];
        });

        vector<vector<int>> ans;

        int st=intervals[0][0],end=intervals[0][1];
        for(int i=1;i<intervals.size();i++)
        {
            if(intervals[i][0]<=end)
            {
                end=max(end,intervals[i][1]);
            }
            else 
            {
                ans.push_back({st,end});
                st=intervals[i][0];
                end=intervals[i][1];
            }
        }
        ans.push_back({st,end});
        return ans;

    }
};

56合并区间

思路

  1. 区间排序:

    • 首先对所有区间进行排序,排序规则是先按区间的起始位置(a[0])升序排列
    • 若起始位置相同,则按区间的结束位置(a[1])升序排列
    • 排序的目的是让后续的合并过程可以按顺序进行,确保相邻的区间在物理位置上也相邻
  2. 区间合并逻辑:

    • 初始化st和end为第一个区间的起始和结束位置
    • 从第二个区间开始遍历:
      • 若当前区间的起始位置intervals[i][0]小于等于end,说明两个区间重叠或相邻,将end更新为两个区间结束位置的最大值(合并区间)
      • 若当前区间的起始位置大于end,说明两个区间不重叠,将之前合并好的区间[st, end]加入结果集,然后更新st和end为当前区间的起始和结束位置
    • 遍历结束后,将最后一个合并的区间加入结果集
  3. 示例说明:

    • 对于输入[[1,3],[2,6],[8,10],[15,18]],排序后不变
    • 合并过程:[1,3]与[2,6]合并为[1,6],然后[8,10]和[15,18]保持不变
    • 最终结果为[[1,6],[8,10],[15,18]]

该算法的时间复杂度主要由排序步骤决定,为O(n log n),空间复杂度为O(1)(不考虑存储结果所需的空间),是区间合并问题的经典高效解法。

代码

复制代码
class Solution {
public:
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
        sort(intervals.begin(),intervals.end(),[](const vector<int> &a,const vector<int> &b)
        {
            if(a[0]!=b[0])
            {
                return a[0]<b[0];
            }
            return a[1]<b[1];
        });

        vector<vector<int>> ans;

        int st=intervals[0][0],end=intervals[0][1];
        for(int i=1;i<intervals.size();i++)
        {
            if(intervals[i][0]<=end)
            {
                end=max(end,intervals[i][1]);
            }
            else 
            {
                ans.push_back({st,end});
                st=intervals[i][0];
                end=intervals[i][1];
            }
        }
        ans.push_back({st,end});
        return ans;

    }
};

189轮转数组

思路

这段代码实现了数组的向右旋转操作,采用了基于最大公约数(GCD)的环状替换算法,是一种高效的原地旋转方法。具体解析如下:

核心思路

利用数组长度 n 和旋转步数 k 的最大公约数(GCD)来确定旋转的 "环" 数量,每个环内的元素通过环状替换完成旋转,从而实现整体数组的旋转效果。

步骤分解

  1. 特殊情况处理 :当 k=0 时,无需旋转,直接返回。

  2. 计算最大公约数:

    • 通过自定义的 mygcd 函数计算数组长度 nums.size() 与旋转步数 k 的最大公约数 ma。
    • 这个 ma 决定了需要处理的环的数量(即需要进行 ma 次独立的环状替换)。
  3. 环状替换过程:

    • 对每个环(从 pos=0 到 pos < ma)进行处理:
      • 保存当前位置 pos 的元素值 last。
      • 通过 now = (now + k) % n 计算下一个要替换的位置。
      • 依次将 last 的值放入下一个位置,同时更新 last 为被替换的元素值。
      • 当 now 回到初始位置 pos 时,完成一个环的替换,将最后保存的 last 放入 pos 位置。
    • 递增 pos,处理下一个环,直到所有环都处理完毕。

优势分析

  • 空间效率 :原地旋转,仅使用常数级额外空间(O(1))。
  • 时间效率 :每个元素仅被移动一次,总时间复杂度为 O(n)。
  • 适用性 :适用于任意长度的数组和任意旋转步数,包括 k 大于数组长度的情况(通过取模自动处理)。

例如,对于数组 [1,2,3,4,5,6] 和 k=2:

  • 数组长度为 6,GCD(6,2)=2,需要处理 2 个环。
  • 第一个环(pos=0):0→2→4→0,元素依次替换。
  • 第二个环(pos=1):1→3→5→1,元素依次替换。
  • 最终结果为 [5,6,1,2,3,4],实现了向右旋转 2 步的效果。

这种算法巧妙利用数学性质减少了操作次数,是数组旋转问题的最优解法之一。

代码

复制代码
class Solution {
public:

    int mygcd(int a,int b)
    {
        if(a<b)swap(a,b);
        if(b==0)return a;
        return mygcd(b,a%b);
    }

    void rotate(vector<int>& nums, int k) {
        int pos=0;
        if(k==0)return;
        int ma=mygcd(nums.size(),k);
        while (pos < nums.size() && pos < ma)
        {
            int last = nums[pos];
            int tmp;
            int now = pos;
            now += k;
            while (now != pos)
            {
                //cout<<now<<endl;
                now %= nums.size();
                tmp = nums[now];
                nums[now] = last;
                last = tmp;
                now += k;
                now %= nums.size();
            }
            nums[pos] = last;
            pos++;
        }
    }
};

238除自身以外数组的乘积

思路

算法思路解析:

  1. 核心思想:

    • 利用两次遍历,分别计算每个元素左侧所有元素的乘积和右侧所有元素的乘积
    • 将这两个乘积相乘,即可得到每个位置除除自身外所有元素的乘积
  2. 具体步骤:

    • 第一次遍历(左到右):

      • 初始化 answer[0] = 1(第一个元素左侧没有元素,乘积为 1)
      • 对于 i > 0,answer[i] 存储 nums[0] 到 nums[i-1] 的乘积(即当前元素左侧所有元素的乘积)
    • 第二次遍历(右到左):

      • 初始化 R = 1(右侧乘积的初始值)
      • 对于每个 i,answer[i] 乘以 R(即当前元素右侧所有元素的乘积)
      • 更新 R 为 R * nums[i](将当前元素加入右侧乘积,供左侧元素使用)
  3. 优势分析:

    • 避免了使用除法(处理了数组中可能包含 0 的情况)
    • 仅使用常数额外空间,效率极高
    • 两次线性遍历,时间复杂度为 O (n)

代码

复制代码
class Solution {
public:
    vector<int> productExceptSelf(vector<int>& nums) {
        int length = nums.size();
        vector<int> answer(length);

        answer[0] = 1;
        for (int i = 1; i < length; i++) {
            answer[i] = nums[i - 1] * answer[i - 1];
        }
        int R = 1;
        for (int i = length - 1; i >= 0; i--) {

            answer[i] = answer[i] * R;

            R *= nums[i];
        }
        return answer;
    }
};

41缺失的第一个正数

思路

代码

复制代码
class Solution {
public:
    int firstMissingPositive(vector<int>& nums) {
        for(int i=0;i<nums.size();i++)
        {
            while(nums[i]>0&&nums[i]<nums.size())
            {
                swap(nums[i],nums[nums[i]-1]);
                if(nums[i]<=0||nums[i]>=nums.size()||nums[i]==i+1||nums[i]==nums[nums[i]-1])break;
            }
        }

        for(int i=0;i<nums.size();i++)
        {
            if(nums[i]!=i+1)return i+1;
        }

        return nums.size()+1;
    }
};
相关推荐
奋发向前wcx2 小时前
CSP-J复赛模拟赛4 王晨旭补题 2026.10.5
算法
念何架构之路5 小时前
zap采样器与性能优化内幕
算法·性能优化·哈希算法
晒太羊的猫6 小时前
hot100动态规划刷题
算法·动态规划
weixin_531094696 小时前
heap_4内存管理
java·开发语言·算法
余额瞒着我当琳6 小时前
红黑树的实现--红黑树的概念、规则、效率、结构、旋转、查找、验证
数据结构·c++·算法
程序员南飞6 小时前
win系统安装minio
java·数据结构·算法
青少儿编程课堂6 小时前
AC自动机多模式串匹配精讲:校园关键词巡检实战解析
c++·python·算法·bfs·信息学竞赛
我命由我123457 小时前
Photoshop - Photoshop 矢量蒙版
学习·职场和发展·产品运营·求职招聘·职场发展·产品经理·photoshop
longlongzihan7 小时前
LeetCode 5. 最长回文子串:从暴力匹配到中心扩展的思维演进
c++·算法·leetcode
waoooqwe7 小时前
问卷样本真实吗
大数据·数据库·算法·数据分析