本文无意引战,只是陈述自己在学习 CS 过程中的感受。

声明如下

  1. 本文观点通过对大多数情况的不完全归纳得到,CS 吊车尾和非 CS 怪物的存在并未纳入考虑范围。此外,非科班生和科班生的选取遵守对照原则和单一变量原则——在本文中具体体现为专业排名相近、智力相近、性别相同、性格相近等,评价指标为算法理解能力、工程代码能力。

  2. 本文观点并不是建立在严谨的实验或推理上得到的,并不具备可信度,权当玩笑话。

  3. 本文所讨论的 CS 科班生为系统学习了 CS 核心课程的人、并不局限于计算机专业

  4. 图源来自网络,如果有侵犯您的权益,请联系作者以删除。


欢迎来到正文部分

随着对 CS 了解的加深,我愈发有这样一种感觉——计算机的学生学的真的是计算机,所有的课程、分支都是
在教你用得好(如软件工程)、用的新(如人工智能、图形学)、用的妙(如计组、算法)。这让我有些担心——计算机鲜明、
强烈的工具导向是否会逐渐磨灭我们那种 wow 的感觉和提问的乐趣呢?有失必有得,回报就是对计算机的理解的加深。

Matt Might 在 What every computer science major should know 中谈到如何学体系结构时,认为 Computer scientists should understand a computer from the transistors up.

在我刚入学的时候也常常听人说起:计算机学生大四毕业的时候所有学过的课程都会在脑海里串成一张相互联系的网络。
这种网络,是 CS 学生用自己的时间堆出来的,也是科班生与非科班生一个重大差异

下面本文就一道简单的算法题为例具体谈谈这种让人“舒服”的联系

这是 LeetCode 上的一道中等难度的位运算题

题目链接在这里:大家之后可以去刷一下
只出现一次的数字 II

题目简介

给你一个整数数组 nums ,除某个元素仅出现一次外,其余每个元素都恰出现三次 。请你找出并返回那个只出现了一次的元素。

示例:
输入:nums = [2,2,3,2]
输出:3

暴力算法

首先,能得到正确结果的算法 >> 优美但只能看的算法
循着这种思想,我们通常会写一个暴力算法理清思路

int singleNumber(vector<int>& nums) {unordered_map<int, int> numTimes;...for (int num : nums) {++numTimes[num];}...
}

不要抱有饶幸心理,暴力算法肯定不能通过的,实际中用暴力的情况也挺少,就算要用,都要加一大堆的优化

位运算优化

接下来要做的,就是应这道题的标签——位运算,从数字的二进制表示去找规律

如果你找不到,不妨把数字写下来,送给你认识的小学生的家长,他们的孩子可是这方面的能手

你看这些小学生多么认真,你过年过节好意思不送人一份试卷大礼包吗?

这道题的规律还是挺好找的,除了 1 个妖怪,其他的数字都出现了 3 遍。将情况进行极端简化就是 000 111 000 111 … 1 或者 000 … 0

如果没有妖怪的存在,那么 0 和 1 的个数都是 3 的整数倍。谁多了 1 个就代表那个数字是谁。

把这种思想推广到每一个位上,不难得到下面的代码

int singleNumber(vector<int>& nums) {int ans = 0;for (int i = 0; i < 32; ++i) {int cnt = 0;for (int num : nums) {// 这一步的等式右边是取出num的第i位二进制表示cnt += ((num >> i) & 0x1);}if (cnt % 3 == 1) {ans |= (0x1 << i);}}return ans;
}

非科班生做到这里基本上就准备收笔了。他们碰到位运算,一般就是找点数字表示规律加上一些数学性质(如余数的性质)就完了。

数电优化

但是,当看到问题的解可以伸到数据的二进制表示的时候,一名 CS 科班生他就兴奋起来了。耗子滴滴,向数电进发、向计组进发、向计算方法进发

由于本人知识浅薄,对计组层面的了解远远达不到实现有效率优化的地步,加之这个层面的优化涉及到不同的指令集。如针对 MIPS 和 X86 的改良版本不同,后面本文主要谈数电和计算方法层面的优化

如果从算法的角度来看,在位运算的区域里已经基本无法改进了。仔细分析,就会发现一个潜在的思路——1 位和 1 个整体有区别吗?是否可以直接对整体进行处理呢?这就引出了后面的数电方法

你的数电复习课来了

如何设计组合逻辑电路

  1. 确定输入输出变量
  2. 写真值表
  3. 写逻辑表达式
  4. 化解逻辑表达式
  5. 用门器件或 MSI 实现(毕竟用不到那么多,就写到这里)

输入变量当然是数组中的数了,那输出变量是什么呢?

回顾前面的思路,我们想得到的其实是最后结果每一位的二进制数。可以猜想输出变量是一个类似 (ai, bi, ci…)这种向量形式 的东西。由题意可得,输出变量应该是 cnticnt_icnti​ mod 3 的结果,即 0 / 1 / 2。但二进制里可没 2 呀,这可咋整?难不成弄一个 3 进制?

这里就用到存储中经常出现的一种处理方法,范围不够、位数来凑。多了咋办,不要就完了呗

于是我们尝试以(ai, bi)为输入变量进行验证

  • (0, 0)表示 0
  • (0, 1)表示 1
  • (1, 1)表示 2

这里需要注意一点:(ai, bi) 会以 00 -> 01 -> 10 -> 00 的顺序进行循环(“防串味”)

这里不对“防串味”做出具体解释,如果读者理解了前面的思路,那么这里不成问题;否则请读者返回前面思考算法的核心思想

nums[i] 为 0 时不做处理,当 nums[i] 为 1 的时候向后循环一步
注:这里还有一个和题有关的地方,因为题中是 3对1,所以(ai,bi)最后只能是 00/01(从 00 开始)
而 3 个 1/0 都会回到 00,而 0 和 1 分别对应 00 和 01,所以最后只需要返回 b

画真值表、写表达式

最后的结果为

之后我们就可以写出大家不喜欢看但计算机喜欢的代码了

int singleNumber(vector<int>& nums) {int a = 0, b = 0;for (int num : nums) {int ai = (~a & b & num) | (a & ~b & ~num);int bi = ~a & (b ^ num);a = ai;b = bi;}return b;
}

数值计算

聪明的同学会思考,ai的计算方法那么复杂,可不可以简化呢?

通过采用数值计算/凸优化里分别求解,利用新值加快收敛的思想对ai的更新方式进行改进

因为 b 的值好算,那么就先算 b 的值,然后用 bi_old 替代 bi 重新写真值表,列表达式(最后得到的结果确实漂亮)

int singleNumber(vector<int>& nums) {int a = 0, b = 0;for (int num : nums) {b = ~a & (b ^ num);a = ~b & (a ^ num);}return b;
}

文章到这里就完了。其实写这样一篇文章并不是想说科班生就比非科班的有优越感,毕竟不付诸实践的都是空中楼阁。
而且,在实际情况中,解决问题 >> 掌握知识


为了方便读者阅读和博客传播,我建了一个公众号 xioacd99

公众号还提供每周科技资讯精选(我一直想做终于去做的东西)

就 计算机 而言,为什么大多数情况下非科班生 比不上 科班生相关推荐

  1. 在19计算机考研炸掉的情况下,21计算机考研的难度会很大吗?

    来源:知乎 作者:注册个号逛一逛 链接:https://www.zhihu.com/question/324725848/answer/820167312 计划规划好,难度能减少一点点. 最重要的一条 ...

  2. python3中的int类型占64位_在windows 10 64位计算机中,默认情况下,numpy数组数据类型将以int32形式出现...

    最初的海报Prana问了一个非常好的问题."为什么在64位计算机上,整数默认设置为32位?"在 据我所知,简短的回答是:"因为它的设计是错误的". 显然,64位 ...

  3. 检测网络是否稳定的计算机命令,网络不稳定情况下,该如何快速检测?

    原标题:网络不稳定情况下,该如何快速检测? 在我们使用电脑时,最讨厌的两种情况一是电脑卡顿而是网络缓慢.一般情况下,电脑卡顿我们可以自己优化加速,但是网络则是没有办法.在我们平时看视频或是浏览网站时, ...

  4. URLEncode的作用到底是什么呢?什么情况下非要用URLEncode方法呢?

    框架用多了,好多细节都没有注意到,回到原生PHP,对一些细节进行在学习. 今天碰到urlencode函数,很是纳闷这个东西干什么用的,百度之,终于搞明白了,简单总结就是你要放入URL的变量要做URL编 ...

  5. ios 弱网 数据丢失_在不丢失数据的情况下将您的iOS设备与新计算机同步

    ios 弱网 数据丢失 Syncing your existing iOS device with a new computer can be a daunting task, especially ...

  6. R语言非独立多分组非参数检验、Kruskal–Wallis检验进行非独立多分组非参数检验(Nonparametric multiple comparisons)、当ANOVA不满足条件的情况下

    R语言非独立多分组非参数检验.Kruskal–Wallis检验进行非独立多分组非参数检验(Nonparametric multiple comparisons).当ANOVA不满足条件的情况下.R语言 ...

  7. 关于socket阻塞与非阻塞情况下的recv、send、read、write返回值

    recv: 阻塞与非阻塞recv返回值没有区分,都是 <0:出错,=0:连接关闭,>0接收到数据大小, 特别:非阻塞模式下返回 值 <0时并且(errno == EINTR || e ...

  8. target存放的是编译后的.class文件地方 默认情况下不会讲非class文件放入进入 如果要使用非.class文件 需要通过增加配置方式自动加入文件...

    target存放的是编译后的.class文件地方 默认情况下不会讲非class文件放入进入 如果要使用非.class文件 需要通过增加配置方式自动加入文件 转载于:https://www.cnblog ...

  9. 非多态的继承情况下,基类指针可以指向派生类对象么?

    class Base { // 基类 public:Base(int aa=88) : a(aa) {}void f() { // 非virtualcout<<"Base&quo ...

  10. 非局域网情况下ROS开发利器——Husarnet

    非局域网情况下ROS开发利器--Husarnet 1. 开发难题 2. 使用 2.1. 软件安装 2.2. 软件安装 2.3. 实测 3. 费用 1. 开发难题 ROS官网很明确的说明: 不同局域网大 ...

最新文章

  1. 【Codevs1322】单词矩阵
  2. 怎么学python-如何高效学 Python?
  3. classpath: spring 中的查找方式
  4. python爬酷狗音乐_良心推荐!一个Python高手必读的库,真香!
  5. dropbox免费容量_免费课程:使用ES6和Dropbox构建费用管理器
  6. diff git 指定时间_Git 自救指南
  7. 一个项目如何编译多个不同签名、包名、资源等,的apk?
  8. Spring Roo 之 Mysql 连接
  9. Android开发指南-窗口小部件(App Widgets)
  10. 中国移动MM的免流量费策略太不靠谱
  11. linux查找历史记录内容,linux中查看历史记录
  12. java excel checkbox_在Java窗体表格中插入复选框
  13. 因为改 UOM conversion 导致库存数量和財务上的数据错误
  14. 阿里api文档链接地址
  15. 【VSCode】安装VSCode都需要配置什么?
  16. 毕业设计-基于微信小程序的答题系统
  17. 大学四年到现在的阿里技术专家,我做了啥?
  18. 吴洪声:2021, DNSPod, Everywhere.
  19. Aspose.Cells转Pdf正确姿势
  20. 利用Ginkgo适配器实现一个PM2.5/粉尘物/颗粒物检测仪

热门文章

  1. 阿里首席架构师讲解“双十一”亿级流量高并发的系统架构搭建方法
  2. 港股交易系统搭建介绍 — 港股LV2行情
  3. 2016年最新苹果开发者账号注册申请流程最强详解!
  4. Spring——DI
  5. 【嵌入式06】寄存器方式和HAL库方式实现 串口通信“hello windows!”+流水灯
  6. 【剖析 | SOFARPC 框架】系列之 SOFARPC 序列化比较
  7. GRUB4DOS使用大全
  8. HTTPClient模拟登陆开心网001(from javaeye)
  9. 区分苹果开发者的网址(开发者网址和管理您的appid网址)及证书信息
  10. Linux系统打不开gedit文本编辑器