算法打卡|Day2 数组part02
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的更多相关文章
- LeetCode初级算法的Python实现--数组
LeetCode初级算法的Python实现--数组 # -*- coding: utf-8 -*- """ @Created on 2018/6/3 17:06 @aut ...
- 算法与数据结构基础 - 数组(Array)
数组基础 数组是最基础的数据结构,特点是O(1)时间读取任意下标元素,经常应用于排序(Sort).双指针(Two Pointers).二分查找(Binary Search).动态规划(DP)等算法.顺 ...
- 前端与算法 leetcode 189. 旋转数组
目录 # 前端与算法 leetcode 189. 旋转数组 题目描述 概要 提示 解析 算法 # 前端与算法 leetcode 189. 旋转数组 题目描述 189. 旋转数组 概要 把他当做一到简单 ...
- 坐标轴刻度取值算法-基于魔数数组-源于echarts的y轴刻度计算需求
本文链接:https://blog.csdn.net/qq_26909801/article/details/96966372数值型坐标轴刻度计算算法前言算法描述上代码代码运行效果结语前言因实习的公司 ...
- KMP 算法中的 next 数组
KMP 算法中对 next 数组的理解 next 数组的意义 此处 next[j] = k:则有 k 前面的浅蓝色区域和 j 前面的浅蓝色区域相同: next[j] 表示当位置 j 的字符串与主串不匹 ...
- c语言经典算法——查找一个整数数组中第二大数
题目: 实现一个函数,查找一个整数数组中第二大数. 算法思想: 设置两个变量max1和max2,用来保存最大数和第二大数,然后将数组剩余的数依次与这两个数比较,如果这个数a比max1大,则先将max1 ...
- 字符串模式匹配之KMP算法图解与 next 数组原理和实现方案
之前说到,朴素的匹配,每趟比较,都要回溯主串的指针,费事.则 KMP 就是对朴素匹配的一种改进.正好复习一下. KMP 算法其改进思想在于: 每当一趟匹配过程中出现字符比较不相等时,不需要回溯主串的 ...
- KMP算法 --- 深入理解next数组
在KMP算法中有个数组,叫做前缀数组,也有的叫next数组. 每一个子串有一个固定的next数组,它记录着字符串匹配过程中失配情况下可以向前多跳几个字符. 当然它描述的也是子串的对称程度,程度越高,值 ...
- 窥探算法之美妙——寻找数组中最小的K个数&python中巧用最大堆
原文发表在我的博客主页,转载请注明出处 前言 不论是小算法或者大系统,堆一直是某种场景下程序员比较亲睐的数据结构,而在python中,由于数据结构的极其灵活性,list,tuple, dict在很多情 ...
- 翻阅《数据结构与算法javascript描述》--数组篇
导读: 这篇文章比较长,介绍了数组常见的操作方法以及一些注意事项,最后还有几道经典的练习题(面试题). 数组的定义: JavaScript 中的数组是一种特殊的对象,用来表示偏移量的索引是该对象的属性 ...
随机推荐
- 【Python&GIS】GDAL栅格转面&计算矢量面积
GDAL(Geospatial Data Abstraction Library)是一个在X/MIT许可协议下的开源栅格空间数据转换库.它利用抽象数据模型来表达所支持的各种文件格式.它 ...
- Vue_Django 登录注册+图书管理系统
Vue前端 注册页面 点击查看代码 <template> <div class="register"> <el-row :gutter="2 ...
- GPT3与机器翻译的结合:探索新的语言翻译技术
目录 引言 随着全球化的加速和人工智能的快速发展,机器翻译成为了许多企业.机构和个人的痛点.虽然已有多种机器翻译技术,但基于自然语言处理和深度学习的机器翻译一直缺乏有效的解决方案,这导致机器翻译的准确 ...
- Shodan使用指南
Shodan是用于搜索连接到互联网的设备的工具.与搜索引擎可以帮助你找到网站不同,Shodan可以帮助你找到有关台式机,服务器,IoT设备等的信息.此信息包括元数据,例如在每个设备上运行的软件. Sh ...
- EaselJS 源码分析系列--第二篇
在 第一篇 中我们大致分析了从: 创建舞台 -> 添加显示对象-> 更新显示对象 的源码实现 这一篇将主要分析几个常用显示对象自各 draw 方法的实现 让我们看向例子 examples/ ...
- Redis的设计与实现(5)-整数集合
整数集合(intset)是集合键的底层实现之一: 当一个集合只包含整数值元素, 并且这个集合的元素数量不多时, Redis 就会使用整数集合作为集合键的底层实现. 整数集合 (intset) 是 Re ...
- 2023ccpc大学生程序设计竞赛-wh
对于大一的我,只听说线下大型比赛,而第一次参加也必然心情激动,生为大一,由于没有参赛经历,所有不知道参赛技巧,所以三个人像个无头苍蝇一样,跟着榜单做,我作为写码的,其他两名队友负责思路和想法,第一道签 ...
- nacos适配达梦、瀚高、人大金仓数据库及部分源码探究
一.插件实现 1.插件目录结构 2.pom依赖 <dependency> <groupId>com.alibaba.nacos</groupId> <arti ...
- Android文本编辑框点击弹出选择日期框
前言: 个人Android小白,写到这了,就记录一下,希望可以帮助到大家. Android输入框点击弹出日期选择框 // 获取 文本编辑框控制权 EditText returnTime = findV ...
- Centos7快速安装Oracl11g
Centos7快速安装Oracle11g 一.解决虚拟机或低配置的云服务器上安装Oracle的方法有两种: 1)不用图形界面,采用静默方式安装,这种方法的技术难度比较大,Oracle的DBA经常采用这 ...