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

【算法-数组2】有序数组的平方 和 长度最小的子数组

今天,带来数组相关算法的讲解。文中不足错漏之处望请斧正!

理论基础点这里


有序数组的平方

给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。

示例 1:

输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100]
排序后,数组变为 [0,1,9,16,100]
示例 2:

输入:nums = [-7,-3,2,3,11]
输出:[4,9,9,49,121]

提示:

1 <= nums.length <= 104
-104 <= nums[i] <= 104
nums 已按 非递减顺序 排序

进阶:

请你设计时间复杂度为 O(n) 的算法解决本问题

1. 思路

只有正数时,平方的大小就是从头到尾即由小到大。

在这里插入图片描述

那顺序遍历升序数组,作平方,就能得到升序结果。

但有负数时该怎么办?最小的平方应该是从两端趋向中间的最接近0的那个值。
在这里插入图片描述

从这个值往两边走,谁的平方大,谁就先插入结果集。题目要求升序,那我们就从结果集的尾部到结果集的头部放入结果。

要“往两边走”我们用双指针从两边遍历就好啦,谁大谁先插入结果数组。

2. 参考代码

class Solution {
public:// 找0, 双指针从两头向中间找, 平方和大的插入结果集的后面vector<int> sortedSquares(vector<int>& nums) {vector<int> result(nums.size());int left = 0;int right = nums.size() - 1;int insertIndex = result.size() - 1;while (left <= right) { // left==righrt时, nums[left]的平方和也要插入结果集long long squre1 = pow(nums[left], 2);long long squre2 = pow(nums[right], 2);if (squre1 > squre2) {result[insertIndex--] = squre1;++left;} else {result[insertIndex--] = squre2;--right;}}return result;}
};

长度最小的子数组

1. 思路

理解题意

分析如何满足需求

1.1 暴力遍历

两层for,一个指针确定当前想遍历的区间的起始位置,另一个指针遍历来确定终止位置,把所有可能的区间都遍历一遍,一旦区间和大于target,就对比并取最小的长度。

参考代码如下:

class Solution {
public:int minSubArrayLen(int s, vector<int>& nums) {int minLen = INT_MAX;int sum = 0; // 子序列的数值之和int subLength = 0; // 子序列的长度for (int i = 0; i < nums.size(); i++) { // 设置子序列起点为isum = 0;for (int j = i; j < nums.size(); j++) { // 设置子序列终止位置为jsum += nums[j];if (sum >= s) { // 一旦发现子序列和超过了s,更新resultsubLength = j - i + 1; // 取子序列的长度result = result < subLength ? result : subLength;break; // 因为我们是找符合条件最短的子序列,所以一旦符合条件就break,不要再累加元素了}}}return result == INT_MAX ? 0 : result;}
};
1.2 滑动窗口

暴力的方法比较死板:直接把所有可能得区间都遍历一遍。每一次都是静态确认好一个区间 [i, j] ,再累加求结果,有没有办法更灵活地确认这个连续子数组地区间呢?有的。

我们可以维护一个连续子数组的区间(右边的指针固定走,左边的指针能跟就跟,保证长度最小),——滑动窗口。

什么是滑动窗口?其实是双指针的一种应用,两个指针动态移动,维护一个区间,像滑动的窗口一样。

滑动窗口在本题中怎么用呢?

在这里插入图片描述

为什么是end固定往后走,begin根据策略走?

首先,end必须把整个数组遍历一遍;其次,begin作为起始位置,不一定需要固定走(如果区间和不大于等于target,走了有什么意义呢)。

end遍历给定数组nums,当区间和大于target的时候,就得到了当前最小的连续子序列但不是最终的。所以在end往后移动的时候,begin也要根据一定策略追赶end,保证得到最终的最小连续子序列。

begin到底是怎样移动的呢?
  • 如果当前区间是连续子数组,begin就要移动
  • 如果当前区间不是连续子数组,那么begin就不能移动

这样子移动,每次begin移动完,[begin, end]的和都会小于target(不再是连续子数组),但这不影响,因为在它最后还是连续子数组的时候,我们已经用minLen记录了它的长度。这样走下去,就能获取到最短的长度。

2. 参考代码

class Solution {
public:int minSubArrayLen(int target, vector<int>& nums) {int begin = 0; // [begin, end] 就是期望的最短子数组区间int end = 0;int curLen = 0;int minLen = INT_MAX;long long sum = 0;while (end < nums.size()) {sum += nums[end];while (sum >= target) { // 已经是子数组, 开始缩减长度curLen = end - begin + 1;minLen = min(curLen, minLen);sum -= nums[begin++]; // 缩减长度}++end;}return minLen == INT_MAX ? 0 : minLen;}
};

今天的分享就到这里了,感谢您能看到这里。

这里是培根的blog,期待与你共同进步!

http://www.lryc.cn/news/211297.html

相关文章:

  • H5游戏源码分享-接苹果游戏拼手速
  • 详解类生到死的来龙去脉
  • 寻找倒数第K个节点
  • [ROS系列]ubuntu 20.04 从零配置orbslam3(无坑版)
  • 网络协议--TCP的保活定时器
  • leetcode 1353. 最多可以参加的会议数目
  • hadoop权威指南第四版
  • LeetCode75——Day20
  • 搭建微信小程序环境及项目结构介绍
  • Python通过pyecharts对爬虫房地产数据进行数据可视化分析(一)
  • 关于测试组件junit切换testng的示例以及切换方式分享
  • nginx 内存管理(二)
  • 【DevChat】智能编程助手 - 使用评测
  • Geek challenge 2023 EzHttp
  • matlabR2021a正版免费使用
  • 天气数据可视化平台-计算机毕业设计vue
  • 揭秘Java switch语句中的case穿透现象
  • Java-API简析_java.io.FilterOutputStream类(基于 Latest JDK)(浅析源码)
  • C语言 每日一题 PTA 10.29 day7
  • 持续集成部署-k8s-服务发现-Ingress 路径匹配与虚拟主机匹配
  • selenium工作原理和反爬分析
  • windows电脑安装系统后固态硬盘和机械硬盘的盘符号顺序显示错乱,解决方法
  • 自定义控件的子控件布局(onLayout()方法)
  • vscode提取扩展出错xhr
  • Docker 笔记(上篇)
  • python自动化测试(六):唯品会商品搜索-练习
  • 深度强化学习用于博弈类游戏-基础测试与说明【1】
  • 通过requests库使用HTTP编写的爬虫程序
  • 550MW发电机变压器组继电保护的整定计算及仿真
  • Linux 命令|服务器相关