不容易解的题10.5
31.下一个排列
31. 下一个排列 - 力扣(LeetCode)https://leetcode.cn/problems/next-permutation/?envType=list&envId=ZCa7r67M会做就不算难题,如果没做过不知道思路,这道题将会变得很难。
这道题相当于模拟cpp的next_permutation函数,但是请注意如果直接使用库函数将失去刷题的意义!
这道题的思路是:从后向前的寻找,第一次遇见的呈从左到右递增的两个数,注意我这里说的很详细了,是从后向前的寻找,从左到右递增的第一次遇见的两个数字,找到了以后,以这两个数的较大的那个数为终止条件,从后向前的寻找第一个大于第一次寻找到的第一个数字,将这两个数字交换之后,再将本次的终止条件那个数为起始点,一直到该数组的尾部,进行一次反转,即可得到结果。听着有点像绕口令,模拟一下。
给出例子:123456求它的一些下一个排列应该依次为:
123465、123546、123564、123645、123654
对照我上面说的规律,不难看出,完全符合规律。遵循了,排列一步一步的增大,如何保证一步一步增大?那么就是上面说的那样,从后往前的原因在于,数字越高位越大
我们要求的下一个排列,仅仅应该比给你的排列大一点点,不能太大!
所以我们从后向前找,我们把大数尽量和较低位交换,这样不就能保证我们得到的排列不会太大吗
这里解释了为什么是从后向前找,而不是从前向后,也解释了为什么是第一次遇见的递增,这都是在保证交换的数位处在相对较低的位置上。
再来说一说,为什么要找第一次找到的那两个数中,以第二个数为终止,从后向前找大于第一次寻找的第一个数,这也是保证我们要交换的数字尽可能小,那有的人可能要问了,你怎么知道从后向前就一定能够小呢?你看上面的排列规律,是不是这样的?尽量使低位拿大数,高位拿小数,这也是后面我们为什么对后面一段进行反转的原因,还有就是终止条件是大于等于第一次找到的第二个数的下标,就像是对123456求下一个排列一样,第一次找到的是56,而6后面没有数,那么只能把6和5进行交换了,你多模拟几遍就可以知道这些究竟是为什么了!!
然后需要注意的一点就是,如果排列已经是最大,无法增大了,就直接整体反转就可以了,这也是题目的要求
看代码
class Solution {
public:void nextPermutation(vector<int>& nums) {for(int i=nums.size()-1;i>0;i--){if(nums[i]>nums[i-1]){for(int j=nums.size()-1;j>=i;--j){if(nums[j]>nums[i-1]){swap(nums[j],nums[i-1]);reverse(nums.begin()+i,nums.end());return;} }}}reverse(nums.begin(),nums.end());return;}
};
找到了下一个排列直接返回就可以了,如果循环里没有返回证明不能找到比当前更大的排列,还有一点,不要把最后的全部反转排列写在if里面和里层循环for的外面,之前我就是这样想的,以为它进不去里层循环就意味着需要反转了,模拟一次就知道,其实如果当前排列是最大,那么它连if也进不去,自然不会走到整体反转。
75.颜色分类
75. 颜色分类 - 力扣(LeetCode)https://leetcode.cn/problems/sort-colors/?envType=list&envId=ZCa7r67M这道题不太难,但也是思路题,题做的少,很容易想不出来。
首先不要用sort排序!
先介绍第一种做法,单指针做法,做法十分简单,循环外部,定义变量s0,它有两个作用一是辅助交换,当循环遍历到0这个数字时,与下标s0的位置做交换,此时它就是起到一个下标交换作用,二是记录上一次循环时候,走到了哪里,也就是下一次循环从哪个地方开始,s0停在哪,说明了s0前面都是0,这时候从该位置起,遍历到1,再进行交换,即可完成排列。
class Solution {
public:void sortColors(vector<int>& nums) {int s0=0;for(int i=0;i<nums.size();++i){if(nums[i]==0){swap(nums[i],nums[s0]);s0++;}}for(int i=0;i<nums.size();++i){if(nums[i]==1){swap(nums[i],nums[s0]);s0++;}}}
};
两次循环搞定,时间是On,其实这个还可以简化第二次循环从s0位置开始遍历,因为前面都是0了
第二种思路是双指针
一个s0记录0的位置,一个s1记录1的位置,但是思路和上一个有一点不同。
我们先正常的去交换1,这是为什么等一下会有解释,正常交换1,就是遍历遇到1,就和下标s1位置交换,而0要特殊处理,因为数字0要被排序到1的前面。
怎么处理?遇到0直接交换,然后不要着急使s0向后指,在该位置判断s0位置是否小于s1,如果是,那么把s1位置和当前遍历位置进行交换,因为s1走在右边,s0此时在它的左边的缘故,此时s1左边都是1,这个时候交换s0下标,一定是把1扔出去了,所以要交换回来,然后再使s0和s1下标各自增加1。
这里官方题解的说法一笔带过,没说是为什么
我在这里的解释是:由于s0和s1都做了交换,所以理应进行两个自增,那如果此时s0在s1的右边或者说和s1重叠呢?这样就没进入s0<s1,这时候还该s1自增吗?
答案是应该的,我们这里保证尽量走在s0的前面,这不是闲的
我的理解是:首先如果1需要交换时候,我们只是写了直接交换,如果s1一直在s0左边,那么我们还要接着扩充它的判断,多写代码。
第二点:题意要求我们把0放前面,所以s0下标理应走在s1的左边,这样看着更加合理。
第三点:一直保持s1走在前面,逻辑具有规律性,利于代码书写和思维理解。
class Solution {
public:void sortColors(vector<int>& nums) {int s0=0,s1=0;for(int i=0;i<nums.size();++i){if(nums[i]==1){swap(nums[i],nums[s1]);s1++;}if(nums[i]==0){swap(nums[i],nums[s0]);if(s0<s1&&nums[i]==1)swap(nums[i],nums[s1]);s1++,s0++;}}}
};
以上仅是个人理解,如果不是强行控制s1走前面,而是在两个判断里都写出来s0或者s1走在前面需要如何的调整,那我觉得应该也是可以的,虽然我没有试过。无非就是给对方扔出来了,需要再交换回去呗。
官方题解,这里第二个写的是else if我认为写if更好,因为此时遍历可能是i指向1而s1指向0,我们可以再判断一次防止s1主动把0扔了出去,理论上可以这样理解,但是当然模拟一下知道,这肯定是不可能的,这样的代码只可能是s0把1扔出去,因为i遍历的数字如果是0,第一个if走不进去,而且刻意调整了s1向前走,所以s1指不到之前的0位置。
还有就是,第二个if里的num【i】==1可以不用写,上面我们也解释了为什么扔出的一定是1,可以看前面,我这样写这两句,完全是让代码思路更加吻合常规思想,就是这样理所当然地写。
第三种方法也是双指针
这个双指针是移动0和2而不是0和1。思路有差别,2需要放在后面,所以需要s2在后面开始走
class Solution {
public:void sortColors(vector<int>& nums) {int s0=0,s3=nums.size()-1;for(int i=0;i<=s3;i++){while(i<s3&&nums[i]==2){swap(nums[i],nums[s3]);s3--;}if(nums[i]==0){swap(nums[i],nums[s0]);s0++;}}}
};//这里的s3就是s2的意思
首先需要注意的就是为什么第一个判断部分用while而不是if,这里外层循环是用i<=s3
我先说一下这个点,用s3来控制下标为什么不用nums.size?
i走到s3之后就没必要往后走了,因为s3的后面都是有序
其实不仅仅是这样,如果i向后走会出现错误的,i走到了s3后面,这时i极有可能指向2,那么就把此时s3指向的垃圾数调回去了!
然后再说为什么使用while做第一部分判断,这里其实你可以用if跑一下试试,有用例过不去,我们此时用的s3做判断,每进一次判断,s3才有可能做出减少1的举动,但是不要忘记外层循环i一直再做自增。遇到案例{2,1,2}这样的数据,第一个判断如果用if,而第二个if永远进不去,因为这个数据里没有0,那会导致下一次外层循环i++之后,i指向了1,那么数组下标为0的数据虽然是2,但是永远无法被调整位置,所以很显然,这个while的原因正是要在当前i这个位置是2,而当前s3也是2的时候,再进行一步调整,充分地去利用i这个位置,把更多的2跳到后面,避免略过2,这里就是和上一种双指针完全不同的思路。那为什么第一种你不需要while循环去那么尽力的找数字,也可以找到全部的0和1然后排序呢?我想应该是因为上一种方法,两个指针都指向前面,这里指针是对着走的,同时兼顾后面数据和交换,和前面数字和i交换,肯定比同一侧的数字和i交换情况复杂一些。
然后解释一下为什么前面说了不能让i走向后面已经排完序的2的位置,而外层循环还要让i走到小于等于s3呢?这是要兼顾一种特殊测试用例{2,0,1}交换数据后成了{1,0,2},s3此时指向中间位置下标,然后i++
如果这时没有等于,那么直接跳出循环了
总之这第三种双指针思路需要注意的细节十分的多,虽然代码也短,但是我更倾向于学习第二种双指针的解法,这种还可以稍微好理解一些,而且需要细节少于这种。
43.字符串相乘
43. 字符串相乘 - 力扣(LeetCode)https://leetcode.cn/problems/multiply-strings/?envType=list&envId=ZCa7r67M不要使用竖式模拟的方法,之前看了一些竖式模拟,需要串位来模拟乘积后相加的情景,很麻烦,也不好理解,建议的方法只有一个:数组存储。
用数组存储,从后向前的遍历数字,第一个数的最后一位分别乘上第二个数字的各个位,得到的结果也分别写在数组对应的两个数字下标和的位置,为什么这么写?这是有讲究的后面再说。
我们这道题结合代码看
class Solution {
public:string multiply(string num1, string num2) {if(num1=="0"||num2=="0")return "0";int m=num1.size(),n=num2.size();vector<int>a(m+n-1,0);for(int i=m-1;i>=0;--i){for(int j=n-1;j>=0;--j){a[i+j]+=(num1[i]-'0')*(num2[j]-'0');}}for(int i=a.size()-1;i>0;i--){a[i-1]+=a[i]/10;a[i]%=10;}string ss="";int i=a[0]==0?1:0;for(;i<a.size();++i)ss+=to_string(a[i]);return ss;}
};
第一点需要注意0乘以任何数字都得0,而如果不写这个判断那么如果一方为0,则结果是“”,一个空字符串,而不是字符串0,这里需要额外判断。
然后是,开辟数组多大合适?
虽然说一个m位的数和一个n位的数相乘可能得到一个m+n或者m+n-1位的数
但是只开一个m+n-1的数组也是可以的,这样如果得到结果是m+n位数的话
多出来的一位会都挤在数组第一个数据里,但是两位最大也就是99所以不需要担心会太大。
这里为什么这么写呢?因为做的时候发现如果开m+n的数组,在出现m+n-1的位数结果时候,最后一个位置会多出一个0
如果开m+n的数组,赋值时候应该是向i+j+1位置赋值,如果结果是m+n位数那么正好存的下,如果少一位,则判断前导0情况就可以了
官方题解给出的是开,m+n空间,然后去判断是否出现前导0,也就是相加和为m+n-1位的情况,我们这里的题解直接开m+n-1,就不用判断了。
然后就是往数组里填数,会的人会觉得很简单,没什么要说的,但是我还是要说一说,这里易错点是什么,数组填数采用的是+=而不是=
数组的位置是+=,它存两个数字的不同下标乘积,那么肯定有一些时候会存在一个位置上,比如说
123和456的3*5和2*6的下标和都是在一个位置
这说明了什么?
这道题的思路我们是把乘积放在数组内,同一个下标就相当于模拟竖式乘积时,对应的那个位置
也就是说2*6得到的答案不对应3*6,而是3*5,这是在模拟竖式算术时的错位和行为,得到答案后,遍历数组把每个位置多余10的部分取模然后多出部分加在上一位,再转换为字符串就可以了
也就是说这里的+=既实现了竖式乘积的错位,也实现了竖式相加的那一个步骤。
而填数之后的各个取模操作是为了模拟相加的产生的进位。
都看到这里了如果对您有用的话别忘了一键三连哦,如果是互粉回访我也会做的!
大家有什么想看的题解,或者想看的算法专栏、数据结构专栏,可以去看看往期的文章,有想看的新题目或者专栏也可以评论区写出来,讨论一番,本账号将持续更新。
期待您的关注!
相关文章:
不容易解的题10.5
31.下一个排列 31. 下一个排列 - 力扣(LeetCode)https://leetcode.cn/problems/next-permutation/?envTypelist&envIdZCa7r67M会做就不算难题,如果没做过不知道思路,这道题将会变得很难。 这道题相当于模拟cpp的next_permu…...
后端面经学习自测(二)
文章目录 1、Http1.1和2.0的区别大概是什么?HTTP & HTTPS 2、HTTP,用户后续的操作,服务端如何知道属于同一个用户cookie & session & token手机验证码登录流程SSO单点登录 3、如果服务端是一个集群机器?4、hashmap是线…...
使用Jest测试Cesium源码
使用Jest测试Cesium源码 介绍环境Cesium安装Jest安装Jest模块包安装babel安装Jest的VSC插件 测试例子小结 介绍 在使用Cesium时,我们常常需要编写自己的业务代码,其中需要引用Cesium的源码,这样方便调试。此外,目前代码中直接使用…...
buuctf-[GXYCTF2019]禁止套娃 git泄露,无参数rce
用dirsearch扫一下,看到flag.php 访问一下没啥东西,使用githack python2 GitHack.py http://8996e81f-a75c-4180-b0ad-226d97ba61b2.node4.buuoj.cn/.git/查看index.php <?php include "flag.php"; echo "flag在哪里呢?…...
【逐步剖C】-第十一章-动态内存管理
一、为什么要有动态内存管理 从我们平常的学习经历来看,所开辟的数组一般都为固定长度大小的数组;但从很多现实需求来看需要我们开辟一个长度“可变”的数组,即这个数组的大小不能在建立数组时就指定,需要根据某个变量作为标准。…...
【树】树的直径和重心
目录 一.树的直径 (1)定义 (2)思路 (3)例题 (4)std(第一小问) 二.树的重心 (1)介绍 (2)求重心 (3)例…...
《Attention Is All You Need》论文笔记
下面是对《Attention Is All You Need》这篇论文的浅读。 参考文献: 李沐论文带读 HarvardNLP 《哈工大基于预训练模型的方法》 下面是对这篇论文的初步概览: 对Seq2Seq模型、Transformer的概括: 下面是蒟蒻在阅读完这篇论文后做的一…...
C++笔记之不同buffer数量下的生产者-消费者机制
C笔记之不同buffer数量下的生产者-消费者机制 文章目录 C笔记之不同buffer数量下的生产者-消费者机制0.在不同的缓冲区数量下,生产者-消费者机制的实现方式和行为的区别1.最简单的生产者-消费者实现:抄自 https://mp.weixin.qq.com/s/G1lHNcbYU1lUlfugXn…...
编码文字使用整数xyz 三个坐标 并使用
导航 说明原始描述AI理解的实现代码说明 原始描述 而后期的,相同的s,前缀差距 和 自身权重 要对应的上,或者说 假设每个序列都是三维空间上的点集合,使用最小的空间表达这些信息,整个数据集才是重点。这些点的集合可以 是空间直线或者是曲线 整体的思路是 一个集合能在任…...
创建vue3工程
一、新建工程目录E:\vue\projectCode\npm-demo用Visual Studio Code 打开目录 二、点击新建文件夹按钮,新建vue3-01-core文件夹 三、右键vue3-01-core文件夹点击在集成终端中打开 四、初始化项目,输入npm init 一直敲回车直到创建成功如下图 npm init 五…...
Flutter笔记 - 用于描述Align的Alignment、AlignmentDirectional、AlignmentTween类
Flutter笔记 用于描述Align的Alignment、AlignmentDirectional、AlignmentTween类 作者:李俊才 (jcLee95):https://blog.csdn.net/qq_28550263 邮箱 :291148484163.com 本文地址:https://blog.csdn.net/qq_…...
门面模式简介
门面模式简介 门面模式(Facade Pattern)是一种结构性设计模式,它提供了一个简化复杂系统的接口,允许客户端通过一个统一的接口与系统交互,而不需要了解系统内部的复杂性。这个模式的目标是降低客户端与系统之间的耦合…...
2023年7月工作经历二
invoke的翻译 C#的这个关键字很熟,但不知道如何翻译比较好。和网友沟通,并查阅多篇博文,觉得“同步调用(invoke)和异步调用(beginvoke)”比较好。 VS2022很爽 C#的类名,会提示命名空间。C调试的时候&…...
7.wifi开发【智能家居:终】,实践总结:智能开关,智能采集温湿,智能灯。项目运行步骤与运行细节,技术归纳与提炼,项目扩展
一。项目运行步骤与运行细节 1.项目运行步骤(一定有其他的运行方式,我这里只提供一种我现在使用的编译方式) (1)项目运行使用软件与技术: 1.Virtual linux 使用这个虚拟机进行程序的编译 2.Makefile与shl…...
学习开发一个RISC-V上的操作系统(汪辰老师) — unrecognized opcode `csrr t0,mhartid‘报错问题
前言 (1)此系列文章是跟着汪辰老师的RISC-V课程所记录的学习笔记。 (2)该课程相关代码gitee链接; (3)PLCT实验室实习生长期招聘:招聘信息链接 正文 (1)在跟着…...
【计算机网络】 心跳机制
文章目录 心跳机制应用场景什么是心跳机制心跳包的发送,通常有两种技术 心跳机制 应用场景 在长连接下,有可能很长一段时间没有数据往来。理论上说,这个连接是一直保持连接的,但是实际情况中,如果中间节点出现什么故…...
文心一言 VS 讯飞星火 VS chatgpt (106)-- 算法导论10.1 4题
四、用go语言,重写 ENQUEUE 和 DEQUEUE 的代码,使之能处理队列的下溢和上溢。 文心一言: 在 Go 语言中,我们可以使用切片来实现队列。下面是如何实现 ENQUEUE 和 DEQUEUE 操作,同时处理队列的下溢和上溢的情况&#…...
进程调度算法之时间片轮转调度(RR),优先级调度以及多级反馈队列调度
1.时间片轮转调度算法(RR) round Robin 1.算法思想 公平地、轮流地为各个进程服务,让每个进程在一定时间间隔内都可以得到响应。 2.算法规则 按照各进程到达就绪队列的顺序,轮流让各个进程执行一个时间片(如100ms)。 若进程未…...
ARMv8如何读取cache line中MESI 状态以及Tag信息(tag RAM dirty RAM)并以Cortex-A55示例
Cortex-A55 MESI 状态获取 一,系统寄存器以及读写指令二,Cortex-A55 Data cache的MESI信息获取(AARCH 64)2.1 将Set/way信息写入Data Cache Tag Read Operation Register2.2 读取Data Register 1和Data Register 0数据并解码 参考…...
密码技术 (6) - 证书
一. 前言 前面介绍的公钥密码和数字签名,都无法解决一个问题,那就是判断自己获取的公钥是否期望的,不能确定公钥是否被中间攻击人掉包。所以,证书的作用是用来证明公钥是否合法的。本文介绍的证书就是解决证书的可靠性的技术。 二…...
【算法学习】-【双指针】-【盛水最多的容器】
LeetCode原题链接:盛水最多的容器 下面是题目描述: 给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。…...
JAVA面经整理(8)
一)为什么要有区,段,页? 1)页是内存和磁盘之间交互的基本单位内存中的值修改之后刷到磁盘的时候还是以页为单位的索引结构给程序员提供了高效的索引实现方式,不过索引信息以及数据记录都是记录在文件上面的,确切来说是…...
【Java 进阶篇】JDBC数据库连接池Druid详解
在Java应用程序中,与数据库进行交互是一个常见的任务。为了更有效地管理数据库连接并提高性能,数据库连接池是一种常见的解决方案。Druid是一个流行的JDBC数据库连接池,它具有丰富的功能和高性能。本博客将详细介绍Druid连接池,包…...
Linux——指令初识
Linux下基本指令 前言一、 ls 指令二、 pwd命令三、cd 指令四、 touch指令五、mkdir指令六、rmdir指令 && rm 指令七、man指令八、cp指令九、mv指令十、cat指令十一、.more指令十二、less指令十三、head指令十四、tail指令总结 前言 linux的学习开始啦! 今…...
专题一:双指针【优选算法】
双指针应用场景: 数组划分、数组分块 目录 一、移动0 二、复写0 从后向前 三、快乐数 链表带环 四、盛水最多的容器 单调性双指针 五、有效三角形个数 单调性双指针 六、和为s的两个数字 七、三数之和 细节多 需再练 一、移动0 class Solution { public:void move…...
蓝桥等考Python组别十二级007
第一部分:选择题 1、Python L12 (15分) 运行下面程序,输出的结果是( )。 lis = [A, B, C, D, E, F] print(lis[0 : 3]) [A, B, C][A, B][A, B, C, D][B, C, D]正确答案:A 2...
全方位介绍工厂的MES质量检验管理系统
一、MES质量检验管理系统的定义: MES质量检验管理系统是基于制造执行系统的框架和功能,专注于产品质量的控制和管理。它通过整合和优化质量检验流程,提供实时的数据采集、分析和反馈,帮助工厂实现高效的质量管理。该系统涵盖了从…...
避免风险,亚马逊、沃尔玛、阿里国际站选择什么样的测评方式最安全?
亚马逊、沃尔玛、速卖通、阿里国际站上做测评是最有效的推广手段之一,而测评又存在很大的风险。但是测评的风险来自哪里?什么样的测评方式才安全呢? 因为平台大数据风控点很多,根据洪哥六七年的测评经验,风控包括以下…...
【C语言】语法--联合体union详解
本文参考博客: https://blog.csdn.net/m0_57180439/article/details/120417270 定义及示例: 联合是一种特殊的自定义类型,该种类型定义的变量也包含一系列的成员,特征是这些成员共用同一块空间,所以联合体也被称为共用体。 #include<stdio.h> union Un//联合类型…...
接口测试复习
一。基本概念 接口概念:系统与系统之间 数据交互的通道。 接⼝测试概念:校验 预期结果 与 实际结果 是否⼀致。 特征: 测试⻚⾯测试发现不了的问题。(因为:接⼝测试 绕过前端界⾯。 ) 符合质量控制前移理…...
济南论坛网站建设/市场调研报告范文大全
通常我们在写存储过程的时候会用到拼字符串的情况,特别是表设计采用分表设计的时候,会较常用到拼字符串,在存储过程中如果遇到下面这样的程序段结果会如何? declare Sql nvarchar(2000),id intset id1set Sqlselect UserID from t…...
怎么直接做免费网站吗/营销管理制度范本
思路:树形dp,d1[i]表示以i为根节点向下的最高高度,d2表以i为根节点的向下的次高高度,p1,p2记录节点高度,up[i]表示以i为根向上的最高高度 代码: class Solution { public:vector<vector<int>> g;vector&…...
网站设计第一步怎么做/北京网优化seo优化公司
DearMob iPhone Manager 是Mac平台上一款功能强大的iPhone数据传输工具,无需iTunes即可完成数据传输。DearMob iPhone Manager Mac版能够为您进行影片,音乐,照片,通讯录等内容进行传输或备份。本次小编为您带来了DearMob iPhone M…...
基于jquery做的网站/市场营销说白了就是干什么的
数组定义、特点、运算符:算术运算 --(自减 自加) 赋值运算发 比较:! 逻辑运算 有 && || ! 正则表达式 修饰符 i:用来表示 g:很少演示(在第一行使用) m&#x…...
武汉企业网站推广方案/百度爱采购关键词优化
在配置文件的随机方法 #随机字符串 com.forwy.value${random.value}#随机 int com.forwy.int${random.int}#随机 long com.forwy.long${random.long}#随机 int (10以内) com.forwy.int${random.int(10)}#随机 int (10~20) com.forwy.int${random.int[10,20]}多环境配置…...
pis粉丝做的网站/百度电脑版下载
2019独角兽企业重金招聘Python工程师标准>>> 1. 使用 synchronized 关键字,代码如下 synchronized(anObject) { value map.get(key);} 2、使用 JDK1.5提供的锁(java.util.concurrent.locks.Lock)。代码如下 lock.lock(); value…...