当前位置: 首页 > news >正文

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. 区间合并逻辑

    • 初始化stend为第一个区间的起始和结束位置
    • 从第二个区间开始遍历:
      • 若当前区间的起始位置intervals[i][0]小于等于end,说明两个区间重叠或相邻,将end更新为两个区间结束位置的最大值(合并区间)
      • 若当前区间的起始位置大于end,说明两个区间不重叠,将之前合并好的区间[st, end]加入结果集,然后更新stend为当前区间的起始和结束位置
    • 遍历结束后,将最后一个合并的区间加入结果集
  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 > 0answer[i] 存储 nums[0] 到 nums[i-1] 的乘积(即当前元素左侧所有元素的乘积)
    • 第二次遍历(右到左)

      • 初始化 R = 1(右侧乘积的初始值)
      • 对于每个 ianswer[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;}
};

http://www.dtcms.com/a/431423.html

相关文章:

  • Linux 软件安装和进程管理
  • [创业之路-645]:手机属于通信?还是属于消费类电子?还是移动互联网?
  • 网站建设 交易保障公众号推广一个6元
  • Nodejs--如何获取前端请求
  • 【项目】基于Spring全家桶的论坛系统 【下】
  • 红黑树可视化工具
  • 深圳公司网站建设设徐州关键词优化排名
  • 三角函数速度规划方法介绍
  • 安卓基础组件020-页面跳转传递复杂数据002
  • Linux操作系统-进程(二)
  • 网站建设的工作计划有什么好字体可以导入wordpress
  • 贵州网站公司厦门seo排名
  • 湖南省建设银行网站6装饰设计网站模板
  • 求余运算和数学模运算的知识了解
  • 【LeetCode】26、80、169、189、121、122、55、45、274题解
  • 【Python刷力扣hot100】1. Two Sum
  • 网站建设属于什么行业类别wordpress数据库文件在哪里设置
  • CCF-CSP认证考试 202309-3 梯度求解
  • JavaScript 保留关键字详解
  • 赣州那里有做网站的公司中国最新军事新闻最新消息2023
  • 使用 Python 将文件上传到 Supabase Storage 并记录元数据
  • 测试报告——“问卷考试系统”项目
  • 网站开发者常见问题网站建设 010
  • Digi-Star精准饲喂系统:牧场收益提升的利器,把Digi XBee模块应用到了极致
  • LED点阵屏
  • 图片方向矫正工具,批量处理超高效
  • 网站开发系统源代码模板兔自用主题WordPress
  • 鄢陵县网站wordpress编辑器器更换
  • 安阳网站推广优化点击最多的网站
  • 护理+人工智能研究热点数据分析项目实战(五)