Algorithm

给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素最多出现两次,返回移除后数组的新长度。

不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。

示例 1:

给定 nums = [1,1,1,2,2,3],

函数应返回新长度 length = 5, 并且原数组的前五个元素被修改为 1, 1, 2, 2, 3 。

你不需要考虑数组中超出新长度后面的元素。
示例 2:

给定 nums = [0,0,1,1,1,1,2,3,3],

函数应返回新长度 length = 7, 并且原数组的前五个元素被修改为 0, 0, 1, 1, 2, 3, 3 。

你不需要考虑数组中超出新长度后面的元素。

思路:这里允许最多重复的次数是两次,那么可以用一个变量 cnt 来记录还允许有几次重复,cnt 初始化为1,如果出现过一次重复,则 cnt 递减1,那么下次再出现重复,快指针直接前进一步,如果这时候不是重复的,则 cnt 恢复1,由于整个数组是有序的,所以一旦出现不重复的数,则一定比这个数大,此数之后不会再有重复项。理清了上面的思路,则代码很好写了:

分析:

快指针:遍历整个数组;
慢指针:记录可以覆写数据的位置;
题目中规定每个元素最多出现两次,因此,应检查快指针指向的元素和慢指针指针所指向单元的前一个元素是否相等。相等则不更新慢指针,只更新快指针;不相等时,先将慢指针后移一位,再将快指针指向的元素覆写入慢指针指向的单元,最后更新快指针。

边界:
当数组的长度小于等于 2 时,不需要操作,直接返回原数组即可。

初始化:
快指针用于遍历数组,但算法不可能操作序号小于 2 的元素,因此快指针初始值为 2;
初始状态下,慢指针应紧随快指针之后,因此初始值为 1;

结束条件:
快指针达到数组结尾。

class Solution {public:int removeDuplicates(vector<int>& nums) {int n = nums.size();if(n <= 2){return n;}int sp = 1;for(int fp = 2; fp < n; fp++){if(nums[fp] != nums[sp - 1]){nums[++sp] = nums[fp];}}return sp + 1;}
};

Review

深度学习网络加速与压缩

综述说明一下最近几年来网络加速与压缩的方法

深度网络加速和压缩的第一种方法是Low-Rank低秩分解。由于卷积神经网络中的主要计算量在于卷积计算,而卷积计算本质上是矩阵分析的问题,通过在大学对矩阵分析、高等数学的学习我们知道通过SVD奇异值分解等矩阵分析方法可以有效减少矩阵运算的计算量。

对于二维矩阵运算来说SVD是非常好的简化方法,所以在早期的时候,微软研究院就做过相关的工作来对网络实现加速。后面对于高维矩阵的运算往往会涉及到Tensor分解方法来做加速和压缩,主要是CP分解、Tucker分解、Tensor Train分解和Block Term分解这些在2015年和2016年所做的工作。

应该说矩阵分解方法经过过去的发展已经非常成熟了,所以在2017、2018年的工作就只有Tensor Ring和Block Term分解在RNN的应用两篇相关文章了。

那么为什么Low-Rank不再流行了呢?除了刚才提及的分解方法显而易见、比较容易实现之外,另外一个比较重要的原因是现在越来越多网络中采用1×1的卷积,而这种小的卷积使用矩阵分解的方法很难实现网络加速和压缩。

深度网络加速和压缩的第二种方法是Pruning,简单来说就是把神经网络中的连接剪掉,剪掉以后整个网络复杂度特别是网络模型大小要减小很多。最早在ICLR2016上斯坦福大学提出了一种称为Deep Compression的随机剪枝方法。

由于随机剪枝方法对硬件非常不友好,往往在硬件实现的过程中不一定能够很好地对网络起到加速和压缩的效果。后来大家就想到使用成块出现的结构化Pruning,Filter Pruning,梯度Pruning等方法。

对于结构化Pruning,在ICML2017中有一篇对于权重进行分析剪枝的文章。具体方法是:首先使用Group Sparsity组稀疏的方法对分组特征添加稀疏正则来修剪掉权重矩阵的一些列,然后通过Exclusive Sparsity增强不同权重之间特征的竞争力来学习更有效的filters,两者共同作用取得了很好的Pruning结果。

从另一方面考虑,我们能否对feature map和activation也做一些pruning的工作呢?在ICCV2017的工作中有人通过给每个通道channel添加一个尺度因子scaling factor,然后对这些尺度因子scaling factor添加sparsity regularization,最后根据尺度因子大小对相应的通道channels进行修剪,将一些尺度因子比较小的通道剪掉,实现对整个网络的瘦身效果。

刚才所讲的都是在网络前向传播过程中所做的Pruning,那么我们能否在网络训练的过程中也加入Pruning来加快网络训练的过程呢?ICML2017有一篇文章对网络训练过程中的梯度信息做了分析,通过去掉幅值比较小的梯度来简化网络的反向传播过程,从而加快网络的训练过程。从结果来看,这种方法可以通过仅仅更新1%-4%的权重来实现和原有网络相当的效果。

除了Pruning,还有一种研究较多的方法是Quantization量化。量化可以分为Low-Bit Quantization(低比特量化)、Quantization for General Training Acceleration(总体训练加速量化)和Gradient Quantization for Distributed Training(分布式训练梯度量化)。

由于在量化、特别是低比特量化实现过程中,由于量化函数的不连续性,在计算梯度的时候会产生一定的困难。对此,阿里巴巴冷聪等人把低比特量化转化成ADMM可优化的目标函数,从而由ADMM来优化。

前面两篇文章都是对权重进行量化,那么feature map能否也可以进行量化呢?以前有人考虑过这个问题,将权重和feature map一起进行量化,但在实际过程中非常难以收敛。我们实验室在CVPR2018上提出一个方法,受到两步哈希法的启发,将量化分为两步,第一步先对feature map进行量化,第二步再对权重量化,从而能够将两个同时进行很好的量化。

刚才的量化都是在网络inference过程中,其实量化也可以在训练过程中使用,这是英特尔在NIPS2017提出的Flexpoint方法。我们知道在32位浮点和16位浮点存储的时候,第一位是符号位,中间是指数位,后面是尾数。他们对此提出了把前面的指数项共享的方法,这样可以把浮点运算转化为尾数的整数定点运算,从而加速网络训练。

第四种方法是Knowledge Distillation。这方面早期有两个工作,Knowledge Distillation最早由Hinton在2015年提出,随后Romero提出了FitNets。在Knowledge Distillation中有两个关键的问题,一是如何定义知识,二是使用什么损失函数来度量student网络和teacher 网络之间的相似度。

最后简单讲一下紧致网络设计。我们刚才讲到的几种网络加速和压缩方法都是在原有非常复杂的网络基础上,对它进行量化、剪枝,让网络规模变小、计算变快。我们可以考虑直接设计又小又快又好的网络,这就是紧致网络设计的方法。我们主要讲三个相关的工作。

先介绍谷歌在2017年和2018年连续推出的MobileNets V1和MobileNets V2,其中使用了depthwise的1x1卷积。MobileNets V1是一个在网络非常精简情况下比较高性能的网络,MobileNets V2开始于通道比较少的1×1的网络,然后映射到通道比较多的层,随后做一个depthwise,最后再通过1x1卷积将它映射回去,这样可以大幅减少1×1卷积计算量。

实际上MobileNets中1x1的卷积占有很大的比重,基于这样的原则,旷视科技在CVPR2018提出把1×1的卷积通过分组来减少计算的方法,由于分组以后存在不同通道之间信息交流非常少的问题,他们又在卷积层之间增加channel shuffle过程进行随机扰乱,增加了不同通道之间的信息交流。这是ShuffleNet所做的工作。

最后简单讲一下深度神经网络加速和压缩的发展趋势。

第一,我们发现实际上现在绝大部分加速和压缩的方法,都需要有一个fine-tuning的过程,这个过程需要有一定量的含有标签的原始训练样本,这在实际应用过程中可能会有一定的限制。会有一些Non-fine-tuning或者Unsupervised Compression方法的出现。实际上现在已经有人在研究这方面的东西。

第二,在加速和压缩过程中会涉及到很多参数,甚至还包含很多经验性东西,将来能不能做到尽可能少需要、不需要经验或者参数越少越好的self-adaptive方法。

第三,现在很多加速压缩方法往往都是针对分类问题,未来在目标检测、语义分割方面也会出现类似的工作。

第四,现在很多方法与硬件的结合越来越紧密,对于加速和压缩方面来说也是如此,未来肯定是之间的结合越来越多。最后是二值网络越来越成熟,未来研究的人会越来越多。

Tips

C++中的非引用形参代码例子,就是说明指针和引用他们其实是把真实的值给传进去了,而非引用形参就是仅仅是一个copy而已,所以不会改变。

#include<iostream>using namespace std;
//普通形参,就是copy
void AddOne(int x){x = x+1;
}
// 指针形参,非引用形参,传的是copy
void AddTwo(int *px){*px = *px+2;
}
// 引用形参
void AddThree(int& x){x = x+3;  //真正的加了
}int main() {int a,b,c;a = 1;b = 2;c = 3;cout << "加之前: "<<a<<endl;//并没有真正的把a传进去,传的是a的copyAddOne(a);cout << "加之后: "<<a<<endl;//把b的地址copy一个传进去cout << "加之前: "<<b<<endl;AddTwo(&b);cout << "加之后: "<<b<<endl;//传的是真正的c,不是copycout << "加之前: "<<c<<endl;AddThree(c);cout << "加之后: "<<c<<endl;return 0;
}

下面的代码说明定义的时候是const的形参,我们在传实参的时候既可以传const实参,也可以传非const实参。而定义的时候是非const,那么实际传的时候不能把const指针传给非const对象。

#include<iostream>using namespace std;int add (int x, int y){return x+y;
}int add_2(const int x, const int y){return x+y;
}int main() {int a,b;const int m = 8;const int n = 9;a = 1;b = 2;
//    int k = add(a,b);int k = add_2(a,b);cout << k << endl;k = add_2(m,n);
//    k = add(m,n);cout <<k <<endl;return 0;
}

非引用形参有局限性,当需要传的数值很大的时候,耗时又耗空间。

#include<iostream>using namespace std;void doOp(int x, int y, int &Sumres,int &minusres){Sumres = x+y;minusres = x-y;}// 不需要复制
//引用参数,不是因为要修改实参,而是因为不想复制
bool isShorter(const string &s1, const string &s2){return s1.size() < s2.size();
}//我们应该将不需要修改的形参都定义为const引用
string::size_type find_char(const string &s, char c){string::size_type i = 0;while(i != s.size() && s[i] != c)++i;return i;
}int main() {string s("hello world");int res = find_char(s, 'o');cout << "pos" << res<< "find o"<<endl;int a = 10, b = 2;int Sumres, minusres;doOp(a,b,Sumres,minusres);cout << Sumres << minusres<< endl;string s1("one");string s2("hello");if( isShorter(s1,s2) )cout << "s1 is shorter"<<endl;elsecout << "s2 is shorter"<<endl;return 0;
}

Share

《穷查理宝典》讲述的是查理芒格的传奇一生,里面有很多他投资以及做人做事的哲学。

总结一下:

  1. 要想拥有一件东西,首先得让自己配得上它
    你想要赚钱,那么就得让自己的能力配的上那些钱财。你想要娶一个聪慧美丽的妻子,那么你就得让自己的各方面都得到提升,以吸引对方。

  2. 在你不知道未来的情况下,努力做好手头的事情
    当下不杂,未来不迎,做好你现在应该做的事情,未来的事随他去吧

  3. 当一个学习机器,终身学习
    任何时代都是这样,在现在技术更新迭代飞速,更需要有这种能力。

  4. 总是反过来想
    如果你想拥有糟糕的一生,那么你就可以去嫉妒,怨恨,反复无常,意志消沉,不屑客观,不从其他人的经验学习。如果你想幸福,那么就不要去做那些事情就好了。

  5. 多元思维模型
    多去学一些自己专业以外的东西,如果你手里只有一把锤子,你看什么问题都是钉子,所以,需要构造自己的多元思维。

ARTS-19(C++引用形参,查理芒格的智慧)相关推荐

  1. 《查理·芒格的智慧:投资的格栅理论》读书笔记

    Charles Munger查理·芒格是一位思考者,把自己的深度思考和投资相结合,取得了非凡的成就.幸运的是,他把自己的思考方式告诉大家,同时也分享了他自己的格栅模型.学习那些基础学科的基础理论,并将 ...

  2. 《穷查理宝典》查理芒格箴言录 epub+mobi+azw3

    作者: [美] 彼得·考夫曼 出版社: 上海人民出版社 出品方: 世纪文景 副标题: 查理·芒格的智慧箴言录 原作名: Poor Charlie's Almanack:The Wit and Wisd ...

  3. 巴菲特+查理芒格+投资理论+经典语录+给韭菜的启示

    巴菲特+查理芒格+投资理论+经典语录+给韭菜的启示 巴菲特: 一个老年人在零售店里发现老婆丢了,恰好遇到一个年轻人也在找自己的另一半,老人问:你妻子长什么样?年轻人答:"她可真是个金发美人啊 ...

  4. 查理·芒格近三年的52句经典语录,句句刻心和扎心

    以下内容转载自 https://www.toutiao.com/i6866588603468743179/ 2020 年 Daily Journal 年会文字记录 1,我们不签让自己偷懒的合同,免得自 ...

  5. 查理芒格+终身学习+你的认知就是你的财富的边界

    穷查理宝典+终身学习+你的认知就是你的财富的边界 我不知道如何使你挣钱.但是我知道一万种甚至更多的方式使得你亏钱. 巴菲特是这样说的: 「芒格用思想的力量,拓宽了我的视野,让我以非比寻常的速度从猩猩进 ...

  6. 查理·芒格提炼的9个思维模型

    查理.芒格认为,每个学科都是从一个独特的角度去切入了解这个世界,都是一个摸象的瞎子:要超越普通人的认知决策,就必须掌握多个核心思维模型.以下内容是从查理.芒格的100种思维模型中提炼出的9个,让人受益 ...

  7. 【误判心理学】查理芒格的25种误判心理倾向

    我早就对标准的思维错误非常感兴趣. 然而,在我受教育的年代,非临床心理学在理解错误判断方面 的贡献完全遭到了主流社会精英的漠视.当时对心理学进行研究的人非常少,只 有一群自娱自乐的教授.这种固步自封的 ...

  8. 读查理·芒格---《穷查理宝典》

    最近几个月主要是读技术类书籍,这次在朋友推荐下改了下口味读了一本"术"类书籍---<穷查理宝典>.这本书罗振宇也有过专门的语音解读,有兴趣可以去听一下. 该书主要包含的 ...

  9. 查理·芒格的人类误判心理学

    目录 查理·芒格的人类误判心理学 一.奖励和惩罚超级反应倾向 二.喜欢/热爱倾向 三.讨厌/憎恨倾向 四.避免怀疑倾向 五.避免不一致性倾向 六.好奇心倾向 七.康德式公平倾向 八.艳羡/妒忌倾向 九 ...

最新文章

  1. NoneBot2插件——今日人品
  2. 多线程经典问题之多窗口卖票
  3. django 在保存数据前进行数据校验
  4. 《你必须知道的.NET》,前言
  5. 聊聊如何构建一支自驱团队(一)
  6. TensorFlow构建二维数据拟合模型(2)
  7. linux 魔术分区,Parted Magic-Linux 中的分区魔术师
  8. leetcode题库:3.无重复字符的最长子串
  9. python-基础-面向对象2-异常-模块工厂模式
  10. android studio mac svn插件,Mac下Android Studio升级SVN1.8(使用1.8format来checkout项目)
  11. opencv中Mat、CvMat和IplImage的相互转化
  12. 1.2 Hadoop快速入门
  13. 笔记———No.1 使用matlab画圆
  14. 神器 Wineskin 基础教程
  15. 算法交易:华尔街怪兽的核武器
  16. 微信自动跳转默认浏览器 微信扫一扫直接打开外部浏览器
  17. 计算机应用程序无响应,电脑的程序未响应是什么原因
  18. typora+PicGo-Core+smms上传图床
  19. Lory的编程之旅就此启动
  20. AI软件写作实战测试:写作技巧 - 让智能写作助手变得更加智能化?

热门文章

  1. 互联网思维的六大特性
  2. runtime error r6025
  3. AIGC - Stable Diffusion 学习踩坑实录总结
  4. this关键字全面剖析
  5. 详细教程: android项目集成PayPal 支付
  6. 北京工业大学 C语言课设
  7. 经验之谈-关于实际项目微前端优化
  8. 图像变形算法之meitu瘦脸及放大眼睛(文末含代码)
  9. 统计学基础——两个样本均值(频率)之差的分布
  10. Flutter学习总结(二)开发语言Dart学习