Day2 数组part02


今日任务:977.有序数组的平方 ,209.长度最小的子数组 ,59.螺旋矩阵II



Problem: 977. 有序数组的平方

思路

首先分析这道题,它是一道有序数组平方后排序的题目。观察平方后数组的特性我们发现,平方后最大的数永远是在数组的前后两端。例如【-1,-2,-3,0,1,2】,平方后去掉符号所以最大的数总是在两侧。

所以本题考虑运用前后双指针算法,一前一后两个指针,比较谁的值大就更新到新的数组中去,直到它们相遇(本题要求新数组从小到大,所以我们从后往前放大数)。

解题方法

双指针算法

复杂度

  • 时间复杂度:

$O(n)$

(补充:快排的时间复杂度:for循环:O(n) ️ 快排:O(nlogn))

Code


class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int k = nums.size() - 1;
vector<int> newnums(nums.size(),0);//记住这种初始化操作,可以设置vector长度 for(int j = nums.size()-1, i = 0; i<=j;){
if(nums[i]*nums[i] < nums[j]*nums[j]){
newnums[k] = nums[j]*nums[j];
k--;
j--;
} else{
newnums[k] = nums[i]*nums[i];
k--;
i++;
}
} return newnums; }
};

Problem: 209. 长度最小的子数组

思路

1.前缀和+二分思路:观察到是求连续子数组的和的问题,我们可以用前缀和。首先我们对整个数组求前缀和数组,然后依次对前缀和数组每一项的值加上目标值去二分搜索不超过这个和的最小值那一项,这样得到的项便对应了连续子数组和的最后一项,我们用这一项减去遍历到的起始坐标,就得到了长度。然后依次遍历,依次比较最小长度即可。

2.双指针思路:其实写滑动窗口不需要背步骤,只需要写的时候问自己四个问题,而这四个问题也正是滑动窗口真正核心的部分。解决了这四个问题,代码也写出来了。

1.增大窗口时,要更新窗口内的什么数据?

要计算窗口内数字的和。

2.什么时候窗口要缩小(shrink)?

当窗口内的和大于等于目标长度时缩小。

3.窗口缩小时,更新窗口内的什么数据?

更新窗口长度,并与之前更新的长度比较得出最小长度。另外由于缩小窗口,在缩小窗口之前要先减去当前left指针所在的数值。

4.什么时候更新结果?

在循环缩小窗口的适合更新最小长度。

链接:https://zhuanlan.zhihu.com/p/142048740

解题方法

双指针算法|前缀和+二分

复杂度

  • 时间复杂度:

滑动窗口:$O(n)$

滑动窗口算法的时间复杂度通常是O(n) 的,其中 n 表示字符串或数组的长度。这是因为滑动窗口算法只需要对每个元素至多遍历一遍,同时也只需要在窗口的左右边界上移动,因此总的操作次数不会超过 2n 次。

前缀和+二分:$O(n+lgn)$

  • 空间复杂度:

$O(1)$

Code1:双指针


class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int n = nums.size();
int l=0,r=0;
int minSubArrayLen = INT_MAX;
int sum=0;
while(r<n){
sum += nums[r];
while(sum>=target){
int len = r-l+1;
minSubArrayLen = min(minSubArrayLen,len);
sum-=nums[l];
l++;
}
r++;
}
return (minSubArrayLen == INT_MAX)?0:minSubArrayLen;
}
};

Code2:前缀和+二分


class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int n = nums.size();
vector<int> preSum(n + 1, 0);
for(int i = 1; i <= n; i++) preSum[i] = preSum[i - 1] + nums[i - 1]; int minSubArrayLen = INT_MAX; //每一项遍历搜索
for(int i = 0; i< n; i++){
int tar =target+preSum[i];
int l = i-1;//区间范围搜索
int r = n+1;//区间范围搜索
while(l+1 != r){
int mid =(l+r)/2;
if(preSum[mid] < tar){
l = mid;
}
else r = mid;
} //输出答案时候注意过滤特殊情况
if(l!=i-1 && r!=n+1 ) minSubArrayLen = min(minSubArrayLen, r - i);
}
return minSubArrayLen == INT_MAX ? 0 : minSubArrayLen;
}
};

Problem: 59. 螺旋矩阵 II

思路

蛇形矩阵问题,我们可以用偏移量控制蛇的姿态,撞墙(越界)或重复走路代表着换方向。另外要注意边界条件,我们判断的是如果沿着当前方向走,下一步走出去了才换方向。

解题方法

利用 int dx[4] = {0, 1, 0, -1}和int dy[4] = {1, 0, -1, 0}去模拟四个方向的偏移量。

复杂度

  • 时间复杂度:

$O(n^2)$,取决于这个数组的大小

  • 空间复杂度:

$O(1)$

Code


class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> nums(n, vector<int>(n, 0));
int x = 0, y = 0; //竖着看这是在模拟每个偏移量,分别是向上,向右,向下,向左
int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0}; //这是在记录方向,0。1。2。3代表取数组不同的方向
int d = 0; for (int i = 1; i <= n * n; i++) {
nums[x][y] = i; //这几步骤可以合并在一起,定义两个新的变量的目的是判断按着原来的方向继续走是否会撞墙或走了重复的路。
int new_x = x + dx[d];
int new_y = y + dy[d];
if (new_x < 0 || new_x >= n || new_y < 0 || new_y >= n || nums[new_x][new_y] != 0) {
d = (d + 1) % 4;//取模运算是一个周期函数,要记住,换方向就用取模运算,模几代表在几个数之间循环。
} x = x + dx[d];
y = y + dy[d];
}
return nums;
}
};

算法打卡|Day2 数组part02的更多相关文章

  1. LeetCode初级算法的Python实现--数组

    LeetCode初级算法的Python实现--数组 # -*- coding: utf-8 -*- """ @Created on 2018/6/3 17:06 @aut ...

  2. 算法与数据结构基础 - 数组(Array)

    数组基础 数组是最基础的数据结构,特点是O(1)时间读取任意下标元素,经常应用于排序(Sort).双指针(Two Pointers).二分查找(Binary Search).动态规划(DP)等算法.顺 ...

  3. 前端与算法 leetcode 189. 旋转数组

    目录 # 前端与算法 leetcode 189. 旋转数组 题目描述 概要 提示 解析 算法 # 前端与算法 leetcode 189. 旋转数组 题目描述 189. 旋转数组 概要 把他当做一到简单 ...

  4. 坐标轴刻度取值算法-基于魔数数组-源于echarts的y轴刻度计算需求

    本文链接:https://blog.csdn.net/qq_26909801/article/details/96966372数值型坐标轴刻度计算算法前言算法描述上代码代码运行效果结语前言因实习的公司 ...

  5. KMP 算法中的 next 数组

    KMP 算法中对 next 数组的理解 next 数组的意义 此处 next[j] = k:则有 k 前面的浅蓝色区域和 j 前面的浅蓝色区域相同: next[j] 表示当位置 j 的字符串与主串不匹 ...

  6. c语言经典算法——查找一个整数数组中第二大数

    题目: 实现一个函数,查找一个整数数组中第二大数. 算法思想: 设置两个变量max1和max2,用来保存最大数和第二大数,然后将数组剩余的数依次与这两个数比较,如果这个数a比max1大,则先将max1 ...

  7. 字符串模式匹配之KMP算法图解与 next 数组原理和实现方案

    之前说到,朴素的匹配,每趟比较,都要回溯主串的指针,费事.则 KMP 就是对朴素匹配的一种改进.正好复习一下. KMP 算法其改进思想在于: 每当一趟匹配过程中出现字符比较不相等时,不需要回溯主串的 ...

  8. KMP算法 --- 深入理解next数组

    在KMP算法中有个数组,叫做前缀数组,也有的叫next数组. 每一个子串有一个固定的next数组,它记录着字符串匹配过程中失配情况下可以向前多跳几个字符. 当然它描述的也是子串的对称程度,程度越高,值 ...

  9. 窥探算法之美妙——寻找数组中最小的K个数&python中巧用最大堆

    原文发表在我的博客主页,转载请注明出处 前言 不论是小算法或者大系统,堆一直是某种场景下程序员比较亲睐的数据结构,而在python中,由于数据结构的极其灵活性,list,tuple, dict在很多情 ...

  10. 翻阅《数据结构与算法javascript描述》--数组篇

    导读: 这篇文章比较长,介绍了数组常见的操作方法以及一些注意事项,最后还有几道经典的练习题(面试题). 数组的定义: JavaScript 中的数组是一种特殊的对象,用来表示偏移量的索引是该对象的属性 ...

随机推荐

  1. Self-Instruct 论文解读:利用大模型自己给自己生成指令数据,指令数据自动生成

    总览 大规模"指令调整"的语言模型,即指令微调的LLM,已经表现出非凡的零样本能力,尤其是推广新任务上. 然而,这些模型严重依赖于人类编写的指令数据,而这些数据通常在数量.多样性和 ...

  2. PHP正则按照从大到小的SIGN签名算法

    <?php/** * 签名算法 * @param unknown $key_id S_KEY(商户KEY) * @param unknown $array 例子:$array = array(' ...

  3. WakaTime Readme Stats-开源项目翻译

    寻找不同语言和地区的翻译 #23 Readme中添加了功能标志的开发指标 眼前一亮的Readme统计数据 你是早起的还是夜间的? 你一天中什么时候工作效率最高? 你用什么语言编写代码? 让我们在你的个 ...

  4. fiddler抓包手机和部分app无法连接网络问题

    前言: 最近公司在做app项目,测试环境app包没有调试模式,导致测试过程中无法查看请求接口和请求的参数,故需要通过抓包工具抓包 一)fiddler安装配置 1.下载安装fiddler,这里不说明了, ...

  5. JS中使用Promise.all控制所有的异步请求都完成后,在执行后续逻辑

    使用场景为,在js中连续的几个异步耗时操作,后面的耗时操作需要使用第一个操作的返回结果.例如调用ajax异步接口,需要先创建完主表,然后拿到主表id在去循环创建明细表,等全部创建完成后,弹出提示来,或 ...

  6. 使用Githud 实现分发IPA包遇到的坑

    最近要用到测试包分发,首先想到了,蒲公英,但是把包扔上去,扫描下载的时候发现,现在需要用户登录才能下载,弃了. 又跑到fir ,发现还得实名才能用,还得上传各种证件照,而且好像每天只有10个下载量,. ...

  7. ISP图像处理——紫边Purple Fringing检测

    之前写过文章记紫边的形成原因,以下小结改善方法 图像紫边存在数码相机.监控摄像头等数字成像图像,使用设备在逆光.大光圈条件下拍摄图像的高反差区域容易出现紫边,解决图像自编问题有助设备得到完美图像. 紫 ...

  8. 3D降噪_运动估计块运动匹配

    运动估计 运动估计是视频去噪技术的重要组成之一,计算相邻两帧视频序列各像素的相对运动偏移量,从而得到其运动轨迹. 点 ( i , j ) (i,j) (i,j)和 ( x , y ) (x,y) (x ...

  9. Redis的设计与实现(6)-压缩列表

    压缩列表 (ziplist) 是列表键和哈希键的底层实现之一. 当一个列表键只包含少量列表项, 并且每个列表项要么就是小整数值, 要么就是长度比较短的字符串, 那么 Redis 就会使用压缩列表来做列 ...

  10. 私网部署DNS(BIND)笔记

    准备工作 下载 yum install -y bind bind-utils包含dig.nslookup等调试命令,非必须. yum install -y bind-utils 防火墙 firewal ...