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

刷题笔记:力扣第704、977、209题(数组相关)

力扣第704题-二分查找

1.练手题,简单的二分排序,完整代码如下:

1. int search(int* nums, int numsSize, int target) { 2. // 左边界l初始为数组起点下标0,右边界r初始为数组最后一个元素下标 3. int l = 0, r = numsSize - 1; 4. // 左边界<=右边界时区间内还有元素,持续二分查找 5. while (l <= r){ 6. // 计算中间下标 7. int mid = (l + r) / 2; 8. // 中间值小于目标值,目标在右半区间,更新左边界 9. if (nums[mid] < target){ 10. l = mid + 1; 11. } else if (nums[mid] > target){ 12. // 中间值大于目标值,目标在左半区间,更新右边界 13. r = mid - 1; 14. } else { 15. // 找到目标值,返回对应下标 16. return mid; 17. } 18. } 19. 20. // 循环结束未找到目标,返回-1 21. return -1; 22. }

时间复杂度O(logn),空间复杂度O(1),标准写法。

力扣第977题-有序数组的平方

1.直接算出平方后暴力排序肯定是不可取的,那样的算法时间复杂度为O(nlogn),题目要求时间复杂度为O(n),即遍历一遍数组便能得出答案。

2.初步想法为寻找非正数与正数的分界点,使用左右两个指针来进行比较和排序,完整代码如下:

1. int* sortedSquares(int* nums, int numsSize, int* returnSize) { 2. // 分配和原数组长度相同的内存,存放平方后的结果 3. int* res = (int*)malloc(sizeof(int) * numsSize); 4. // cur 标记结果数组当前存放元素的位置 5. int cur = 0; 6. // r 右指针,寻找第一个非负数下标 7. int r = 0; 8. 9. // 右指针向右移动,找到第一个不小于0的数字 10. while (r < numsSize && nums[r] < 0){ 11. r++; 12. } 13. 14. // l 左指针指向最后一个负数的下标 15. int l = r - 1; 16. 17. // 左右指针都未越界,比较绝对值大小,小的平方先放入结果 18. while (l >= 0 && r < numsSize){ 19. // 左边负数绝对值更小,先存左边平方 20. if (-nums[l] < nums[r]){ 21. res[cur++] = nums[l] * nums[l]; 22. l--; 23. } else { 24. // 右边数字更小或相等,存右边平方 25. res[cur++] = nums[r] * nums[r]; 26. r++; 27. } 28. } 29. 30. // 若左指针还有剩余负数,依次放入结果 31. while (l >= 0){ 32. res[cur++] = nums[l] * nums[l]; 33. l--; 34. } 35. 36. // 若右指针还有剩余非负数,依次放入结果 37. while (r < numsSize){ 38. res[cur++] = nums[r] * nums[r]; 39. r++; 40. } 41. 42. // 给外部参数赋值结果数组长度 43. *returnSize = cur; 44. return res; 45. }

该算法时间复杂度为O(nlogn),满足题目要求。

3.答案提供了另外一种思路,原数组的平方一定是从两端向中间依次递减,所以可以不用排序,将左右指针放置于数组两端,比较平方后更大的那一个逆序放入结果数组。完整代码如下:

1. int* sortedSquares(int* nums, int numsSize, int* returnSize) { 2. // 开辟结果数组,空间大小与原数组一致 3. int* res = (int*)malloc(sizeof(int) * numsSize); 4. // cur 从结果数组末尾开始填充,大数放后面 5. int cur = numsSize - 1; 6. // l 左指针指向数组最左端(负数区),r 右指针指向数组最右端(正数区) 7. int l = 0, r = numsSize - 1; 8. 9. // 左右指针未相遇时循环 10. while (l <= r){ 11. // 左侧数字平方更大 12. if (nums[l] * nums[l] > nums[r] * nums[r]){ 13. // 将大的平方值放入结果数组尾部,游标前移,左指针右移 14. res[cur--] = nums[l] * nums[l]; 15. l++; 16. } else { 17. // 右侧数字平方更大或相等,存入尾部,游标前移,右指针左移 18. res[cur--] = nums[r] * nums[r]; 19. r--; 20. } 21. } 22. 23. // 返回数组长度等于原数组长度 24. *returnSize = numsSize; 25. return res; 26. }

该算法时间复杂度为O(nlogn),满足题目要求。

力扣第209题-长度最小的子数组

1.这道题肯定是使用滑动窗口,初步写出的代码如下:

1. int minSubArrayLen(int target, int* nums, int numsSize) { 2. int l = 0, r = 0; 3. int tmp = 0; 4. int res = 100001; 5. 6. while (r < numsSize && l <= r){ 7. int cnt = r - l; 8. if (tmp < target){ 9. tmp += nums[r++]; 10. } else { 11. res = fmin(res, cnt); 12. tmp -= nums[l++]; 13. } 14. } 15. 16. return res == 100001 ? 0 : res; 17. }

2.初步写的代码连本地算例都没通过,询问ai后得知滑动窗口的处理逻辑有些问题。正确的滑动窗口处理方式应该是右指针一直无条件向前,左指针根据条件向前回退吐出元素。这种错误在力扣第3题犯过,属于时间久了忘记该知识点了,正好通过本题来回忆一下。

3.基于以上思想,写出的完整代码如下:

1. int minSubArrayLen(int target, int* nums, int numsSize) { 2. // 记录满足条件的最小子数组长度,初始值设为大于数组最大可能长度的数 3. int res = 100001; 4. // 滑动窗口内元素累加和 5. int tmp = 0; 6. 7. // 滑动窗口,l窗口左边界,r窗口右边界,右边界不断向右扩张 8. for (int l = 0, r = 0; r < numsSize; r++){ 9. // 将当前右边界数值加入窗口和 10. tmp += nums[r]; 11. // 窗口和大于等于目标值时,尝试收缩左边界,寻找更短合法子数组 12. while (tmp >= target){ 13. // 计算当前窗口长度 14. int cnt = r - l + 1; 15. // 更新最小长度 16. res = fmin(res, cnt); 17. // 左边界右移,窗口缩小,减去移出窗口的数值 18. tmp -= nums[l++]; 19. } 20. } 21. 22. // 如果res未更新说明无满足条件子数组返回0,否则返回最小长度 23. return res == 100001 ? 0 : res; 24. }

时间复杂度为O(n),满足题目要求。

http://www.cnnetsun.cn/news/3727601.html

相关文章:

  • C#通过注册表操作Windows桌面背景:原理、代码与实战
  • C++二进制文件读写:从read/write原理到跨平台实战
  • C++实现RANSAC平面拟合:从原理到工程实践
  • Processing创意编程:从图形绘制到交互设计的核心技术解析
  • 基于DP83630实现亚纳秒级网络时钟同步:硬件PTP PHY设计指南
  • 树鹊磁电王八大品类如何构建无死角的“穿戴式养生”生态系统
  • AI智能教材生成技术:原理、实践与优化
  • 基于压力传感器与ADC的高精度液位监测系统设计全解析
  • TCP协议核心机制解析:从三次握手到可靠传输的工程实践
  • 如何快速掌握Greasy Fork:终极浏览器脚本管理平台完整指南
  • 抖音无水印下载终极指南:5分钟掌握免费高清视频批量下载技巧
  • NBM5100A电池管理IC在低功耗物联网设备中的应用
  • Windows右键菜单终极清理指南:3步快速恢复清爽操作体验
  • 仿冒 Snap 官方社工钓鱼隐私窃取攻击攻防与法律规制研究
  • DeepSeek降AI指令实战:提升大模型输出自然度
  • 深入解析MIPI CSI-2协议引擎:CSI2_CTRL寄存器配置与实战指南
  • CC3220MODx Wi-Fi模块PCB布局与RF设计实战指南
  • 静磁场仿真并行计算与GPU加速实践
  • “数字方志”时代已来:省级地方志办强制接入AI地理语义引擎,2025年前未适配将暂停经费拨付
  • LM96000硬件监控芯片实战:从架构解析到智能风扇控制配置
  • 2026年企业展厅策划选源头工厂:核心优势与避坑要点全解析
  • EVM无线电合规实战:解读加拿大与日本法规,规避研发认证风险
  • 智能电网IED模拟输入输出模块:高精度信号转换与工业级设计解析
  • Zorin OS曾是我的Linux入门神器,现在Ubuntu让我动摇了
  • 3D打印成本三年内将显著下降:从原型验证到车间生产的拐点
  • TAPSO算法解析:三重存档机制优化粒子群性能
  • 从零实现C++ unique_ptr:深入理解独占所有权与RAII机制
  • ViGEmBus虚拟游戏控制器驱动:Windows游戏设备兼容性完整解决方案
  • 自制3D打印机器狗:从开源方案到步态算法的完整实践指南
  • 如何让微信网页版在Chrome、Edge和Firefox中重新可用:wechat-need-web完整实战指南