力扣之867题2021-03-22

一、#867转置矩阵  #数组

时间复杂度为O(mn),空间复杂度为O(1),除了返回值以外,额外使用的空间为常数。

1、有一种情况没有试,这种其实通不过,举例子时应注意举的两个特例的区别,这个要考虑在内

没有考虑转置矩阵的存储问题,其实跟原矩阵已经不一样,区别是行列数的大小不同,需要新建矩阵,不然就会报内存错,堆缓冲区溢出

因为若使用原数组,边界会越界。

2、大体改完的小毛病,注意二维数组元素的书写;定义m,n若都是同一数据类型,可以只写一个int。

3、注意,

vector二维数组已知行数和列数的定义,因为vector容器表示的是一维数组,所以vector<vector>这种形式的数组是二维数组,<>里面是数组的类型;

如何得到vector二维数组的行数和列数;

函数头的参数传送的是地址,局部函数的matrix的值变了,那么原来调用它的函数的值也会改。

4、堆缓冲区的相关知识点(未细看)关于堆栈的讲解(我见过的最经典的)_忆水思寒的博客-CSDN博客_堆栈

堆heap是程序员自己申请,指明大小,由程序员分配释放,用到malloc和free;栈stack是由系统自动分配释放,存放函数参数的值,局部变量的值

二、面试题17.10 主要元素  #数组#分治算法

时间复杂度o(nlogn),空间复杂度o(logn),因为上面先有排序,为快排是o(nlogn),后面的遍历为o(n),而nlogn高于线性n;注意:快速排序是有空间复杂度的

1、一点没想起来思路,先排序;

2、关键词是超过一半的元素一样,所以遍历时遍历为一半加1的次数就行,多了不用;

3、因为排序了,只需要判断这些次数的头和尾元素相同就达标了;可能实际的主要元素的数量比一半加1多,但也不用管

4、我自己参考最高赞后的改进,把for循环遍历的范围从[i+num.size()/2,num.size())变为[0,nums.size()/2+1)了,这样提交后执行时间从20s变为16s,更快,可能前边因为加了一个i的原因?;内存这个不稳定,有时高有时低

5、sort排序参数为数组的起始地址和结束地址,不是数字下标,前提是这个数组是一个vector来表示

6、这样设定遍历次数为一半加1后,找不到相等的就返回-1,比如1233,这种3并没有超过一半

第二种方法:摩尔投票法:

时间复杂度o(n),空间复杂度o(1),这个摩尔投票法要比排序法的时间复杂度要好。

1、一般most要在循环内去开始赋值,for循环一般都是从0开始,不要自己给安排从1,不要循环外赋值,这样一个循环解决所有问题,单独拿出一个在循环外其他的再另外看不容易看出规律,规律要有普适性;

2、cnt初始化为0,为1才算值存在,为1才会代表值,为0什么不代表;

3、要弄清楚先分为两大步来的,一是通过循环判断先把能够解决最后cnt为0的情况,仅仅通过第一步能够解决类似123451,1212,1223,32,不用第二步就能返回得到-1,这里面排除的也包括有最多数的,即众数,也有没有最多数的,即不存在众数的,但数目都没超过一半的情况,这种结果cnt都为0。

所以第二步,需要再for循环对最后cnt>0时的most数计数,看是否超过一半。通过第2步,能解决类似1233,123,121,12212121,12221,125959555,2211122,能排除另一部分cnt>0时数没有超过一半的情况,这里面包括有最多数的,也包括没有最多数的情况。

不能想着一次性就把两个问题同时解决。

4、注意不要被众数误导,这两步骤都会有最多数存在的可能。分步骤的标准不是众数或者是众数,而是cnt==0,或者cnt>0。也就是说这两步其实是在逐步排除可疑的数,第一步就是先用cnt=0前后两个不同的数抵消,大体排除一部分,得到的仍是可疑数,第二步再通过超过一半来精细确定,最后把另一部分再排除。

三、#977 有序数组的平方 #数组#双指针

第一种排序法:

第一种排序法,时间复杂度为o(nlogn),空间复杂度o(logn),除了存储答案的数组以外,我们需要 O(logn) 的栈空间进行排序。

快速排序的空间复杂度?

总结:通常涉及到能够用快速排序算法解决的问题,而快排是所有排序算法中最好的,通常从时间复杂度上不是最好的方法,因为时间复杂度为o(nlogn),要找o(n)的最好,且空间复杂度也不是最好为o(logn),通常会找有没有o(1)的。

我的改成了它,又另外新建了一个数组,这样比较科学,因为用原来的如果是空间变了还会边界溢出,但这样时间变多,内存变多。如果不变,可以用我的法,比较省,不会结果时间和内存都变不好了。

但第一种方法没有用到有序数组的条件,简化复杂度

我自己写的第二种方法,双指针法,执行后结果不好,变得更慢了,只打败了5%这种,原因使用了insert函数。其他的像一些定义一个变量,小函数算大小的调用,算绝对值的调用,一些小运算都没太事。

而参考的下面这个会正常一些,这个与第一种方法新建数组的那一种比较,确实会时间更短了,内存更小了。

时间复杂度o(n),空间复杂度o(1)

1、注意不要使用insert函数,里面还会包括一个begin函数,只要使用这个insert,内存变大,运行时间变长很多。

2、如果用insert函数,只需声明数组,不需要定义数组,不需要设置数组的大小以及初始化,哪怕只设置数组的大小也不行,不然这两个的结果一样都是,后面会有数组大小个0。

所以,用insert只需要声明数组即可。

3、所以把insert用其他方法代替,先定义好数组分配好内存初始化,然后直接用res[k--]赋值即可。

4、因为其他的点并不会太影响,所以怎样写都可以,可以用变量表示size再继续亦可以不,或者平方可以直接相乘也可以用函数pow

5、新建的数组命名和原来数组名不要太相似

6、小问题,++i会更好一点,因为i++多了一个副本,具体详见(C++)i++和++i,哪个效率高一些_suixinsuiyuan33的博客-CSDN博客

注意:

这样

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值