算法打卡|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 中的数组是一种特殊的对象,用来表示偏移量的索引是该对象的属性 ...
随机推荐
- CentOs7安装部署Sonar环境(JDK1.8+MySql5.7+sonarqube7.8)
sonarqube安装前环境准备JDK1.8.MySql5.7. 一.JDK安装 1.下载jdk #打开下面的网址,选择 jdk-8u371-linux-x64.tar.gz 进行下载 (8u371版 ...
- 深度解析SpringBoot内嵌Web容器
你好,我是刘牌! 前言 今天分享一个SpringBoot的内嵌Web容器,在SpringBoot还没有出现时,我们使用Java开发了Web项目,需要将其部署到Tomcat下面,需要配置很多xml文件, ...
- 重新初始化k8s集群
执行如下命令,所有节点都执行 kubeadm reset 初始化集群,仅在master(centos01)上执行 [root@centos01 opt]# kubeadm init --apiserv ...
- Python Django 模版全解与实战
本文首先介绍了Django模板系统的基础知识,接着探讨了如何安装和配置Django模板系统,然后深入解析了Django模板的基本结构.标签和过滤器的用法,阐述了如何在模板中展示模型数据,最后使用一个实 ...
- 1.8 运用C编写ShellCode代码
在笔者前几篇文章中,我们使用汇编语言并通过自定位的方法实现了一个简单的MessageBox弹窗功能,但由于汇编语言过于繁琐在编写效率上不仅要考验开发者的底层功底,还需要写出更多的指令集,这对于普通人来 ...
- uni-app学习之路
MVC模式1. model:模型层,数据的增删改查2. view:视图层,前端页面3. controller:控制层,处理业务 文件页面结构1. 页面以`.vue`结尾2. `template`,`s ...
- quarkus依赖注入之四:选择注入bean的高级手段
欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 本文是<quarkus依赖注入> ...
- vue2 如何实现将dom元素转移到指定节点
背景:在写商城页面时,PC端给的设计图纸是按照宽度1920给的,内部内容区域(main)1191px,写死的指定宽度.然后新出了一个页面,类似于12306的这个页面,图片部分,直接占满了屏幕的100v ...
- [linux]frp内网穿透
前言 假设有如下网络拓扑 A可以访问B,但B无法访问A.A和B都能访问C.如果B需要访问A的8000端口,一般有如下方法: 网络管理员做路由转发.硬件层面网络转发,性能一般来说更好,但需要熟悉路由配置 ...
- linux设置信号量系统参数
前言 信号量是IPC(进程间通信)机制的一种,用于协调多个进程或线程对共享数据的读写操作,本质上是一个计数器.类似于锁,主要用于保护共享资源,控制同时访问资源的进程数. 信号量只允许调用者对它进行等待 ...