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. 你还在用Object.equals()方法吗?

    前言 当<阿里巴巴Java开发手册>发布后,我也是仔细进行了阅读,想从中找出一些"标准",让自己的代码质量提高.手册中对 Object 的 equals 方法的使用进行 ...

  2. XMLConfiguration -- Poco

    Library : Util Package: Configuration Header : Poco/Util.XMLConfiguration.h 此配置类从 XML 文档中提取配置属性. 支持类 ...

  3. 什么是hive的高级分组聚合,它的用法和注意事项以及性能分析

    hive的高级分组聚合是指在聚合时使用GROUPING SETS.CUBE和ROLLUP的分组聚合. 高级分组聚合在很多数据库类SQL中都有出现,并非hive独有,这里只说明hive中的情况. 使用高 ...

  4. 前端Vue自定义带历史记录的搜索框组件searchBar 支持搜索输入框清空 搜索历史存储记录清除

    前端Vue自定义带历史记录的搜索框组件searchBar 支持搜索输入框清空 搜索历史存储记录清除,下载完整代码请访问uni-app插件市场地址:https://ext.dcloud.net.cn/p ...

  5. zabbix 使用监控项原型(自动发现规则)

    以kafka为例,需要先对 topic-parttion 做发现,脚本如下 cat topic_parttion_discovery.py #!/usr/bin/env python import j ...

  6. Linux 软件包:man pages

    有时候,man ls 发现没有帮助文档,可以快递打开浏览器检索 "man ls" . # yum list | grep man | grep pages gl-manpages. ...

  7. linux下的venv使用

    首先安装该模块: sudo apt-get install python3-venv 之后创建用于存储工程的文件夹 mkdir [filename] 创建环境: python3 -m venv ven ...

  8. 静态vlan的划分实验

    静态vlan的划分 1,toupu图 2,配置id与子网掩码 2.1,pc,server的ip与子网配置 pc5 pc6 pc7 pc8 server1 server2 3,vlan的静态划分 1,v ...

  9. 语音合成技术3:HierVST: Hierarchical Adaptive Zero-shot Voice Style Transfer

    HierVST: 分层自适应零样本语音风格转换 摘要: 尽管语音风格转换(VST)领域取得了快速进展,但最近的零样本VST系统仍然缺乏将新的说话者的语音风格进行转换的能力.在本文中,我们提出了Hier ...

  10. [mysql]定制封装MySQL的docker镜像

    前言 基于MySQL的原版镜像做一些个性化配置修改,封装/etc/my.cnf文件到镜像中,并且支持通过环境变量修改innodb_buffer_pool_size.server_id以及自动配置inn ...