技术的浪潮奔腾不息,浪潮退去之后,留给我们自己的是方法论?还是过时的技术?
------
我们程序员,总喜欢谈论所谓“35岁魔咒”,好像“35岁魔咒”成了程序员的专利。然而事实上,35岁,是各行各业的职场人都会面临的问题。
究其根本,35岁是人到中年的转折点,如果我们在工作中的价值产出,更多依靠体力,那么就势必面临职业发展开始走下坡路的困境。
编程,原本是一种极富创造力,重视抽象思维与逻辑推演的工作,但我们相当一部分人,把编程做的像事务性工作,平淡如水,如果这样,“35岁魔咒”就会困扰我们。
在一个社会群体中,不同的人有不同的选择,我无意也无法改变大的环境,但希望帮助有意愿与“35岁魔咒”斗争的程序员,找到一点方向,多干几年!
杨辉三角是我在面试中经常会问的一个问题,”请编程,按照指定格式输出前N行的杨辉三角"。
大部分候选人,拿到问题之后,就开始编码,首先写一个两层的循环,然后开始思考循环的终止条件,经过一番思考,给出一个自己都不相信的答案。我印象比较深刻的一次,候选人来自微信支付,也仅给出了获取前N行数据的方法,仍然未能找到按照指定格式打印的方法。
很多人会说,离开学校好几年了,算法早都忘记了,这种问题应该去问校招的同学。我不以为然,我在意的不是一个具体的算法,而是分析和解决问题的思路。我们可以忘记一些具体的算法,但忘记的同时,应该把算法中蕴含的解决问题的思路内化成自己的武器。
接下来,我和大家介绍下我如何看待这个问题。
图灵奖得主N.Wirth提出"程序 = 算法 + 数据结构",我更习惯说“程序 = 数据 + 过程”。
首先,我们站在数据的视角,来审视这道面试题,可以发现:
1、可以使用二维数组(以php语言为例)描述杨辉三角的前N行数据
[ [1], [1, 1], [1, 2, 1], [1, 3, 3, 1], ]
2、行的数据之间,存在如下规则:
1)每行两边数字恒为1
2)每行中间的数字,是上一行交叉位置两个数字的和
因此,可以用一个伪代码描述这种关系:
F(1) = [1] F(N) = [ 1, F(N-1)[0] + F(N-1)[1], F(N-1)[1] + F(N-1)[2], ..., F(N-1)[N-2] + F(N-1)[N - 1], 1 ]
接下来,我们站在过程视角,审视这道面试题。首先,它的过程可以分为两个步骤:1)获取前N行杨辉三角的数据;2)按照图示对齐的方式进行打印。
第一步,基于我们前面对数据的分析,可以轻易的得出对应的方法设计:
function yanghui_datas($n); // 获取前N行杨辉三角数据 function yanghui_line_datas($prev_line_data); // 依据前一行数据获取下一行数据
第二步,依据图示对齐方式进行打印。单纯的打印是很简单的,所以,关键在于“对齐”。
解决对齐的方法,无非就是给相应的位置留白。但我们发现,该怎么留白是不清晰的。那就进一步思考,导致留白逻辑不清晰的难点问题是什么?
通过分析,可以看到,如果只需要输出前5行,那么每个数字都是个位数,如果要输出第6行,那么就开始有十位数。因此,是数字宽度的不确定性,产生了这里的困难。
逆向思维,如果数字的宽度确定,那就没有这个困难。所以:
我们把每个数字放到一个等宽的格子中。这样,整个问题就清晰了:
格子宽度 = 最大数字宽度 + 1 行前留白 = (LINE_COUNT - LINE_NO) * 格子宽度 / 2 格子内部: (数字居中) 左留白 = (格子宽度 - 数字宽度) / 2 右留白 = 格子宽度 - 左留白 - 数字宽度
经过上面的分析,代码几乎就跃然纸上了。
// 获取前N行杨辉三角数据 function yanghui_datas($n_line) { $datas = []; $prev_line_datas = []; while ($n_line -- > 0) { $line_datas = yanghui_line_datas($prev_line_datas); array_push($datas, $line_datas); $prev_line_datas = $line_datas; } return $datas; } // 通过前一行数据获取下一行数据 function yanghui_line_datas($prev_line_datas) { if (empty($prev_line_datas)) { return [1]; } $line_datas = []; array_push($line_datas, 1); // 行首 for ($i = 1; $i < count($prev_line_datas); $i ++) { array_push($line_datas, $prev_line_datas[$i - 1] + $prev_line_datas[$i]); } array_push($line_datas, 1); // 行尾 return $line_datas; } // 打印指定的杨辉三角数据 function yanghui_print($datas) { $space = ' '; // 留白字符 $newline = '<br />'; // 换行符 $max_num = yanghui_max_num($datas); // 最大数字 $max_num_width = yanghui_num_width($max_num); // 最大宽度 $unit_width = $max_num_width + 1; // 格子宽度 $line_count = count($datas); // 行数 foreach ($datas as $idx => $line_datas) { $line_no = $idx + 1; // 行号 $line_prefix_width = ($line_count - $line_no) * $unit_width / 2; // 行前留白数 echo str_repeat($space, $line_prefix_width); foreach ($line_datas as $num) { $num_width = yanghui_num_width($num); // 数字宽度 $left_width = intval(($unit_width - $num_width) / 2); // 格子内左留白宽度 $right_width = $unit_width - $left_width - $num_width; // 格子内右留白宽度 echo str_repeat($space, $left_width); echo $num; echo str_repeat($space, $right_width); } echo $newline; } } // 获取最大数 function yanghui_max_num($datas) { $max = 0; foreach ($datas as $line_datas) { foreach ($line_datas as $num) { $max = max($max, $num); } } return $max; } // 获取数字的宽度 function yanghui_num_width($num) { return strlen(strval($num)); }
最后,过程的两部分组装起来,就是想要的结果。
function yanghui_dump($n) { $datas = yanghui_datas($n); yanghui_print($datas); }
有人说,杨辉三角中的数字,可以依据坐标直接计算得到,没关系,替换掉获取数据的对应部分即可。
当我们面对问题时,有两种思维模式:经验型和能力型。
经验型思维,搜索自己的知识库,发现杨辉三角应该要一个两层循环,就开始执行;执行了一步之后,发现卡住了,下一个问题自己的知识库中没有,然后就陷入了沉思!
能力型思维,先分析问题的本质构成,对问题进行分解,将复杂的大问题转换成多个简单的小问题,抽丝剥茧,在自己的知识库中搜索每个小问题的答案,最终解决问题。
两种思维模式的优劣势显而易见,经验型思维适合解决确定的、已知的、简单的问题,效率更高;能力型思维适合解决不确定的、未知的、复杂的问题,适应性更广。
编程,是一项极富创造力,注重逻辑和推演的工作。
当我们开始编程之前,首先需要站在具体问题的层面,对目标系统进行分析,然后,又需要站在抽象视角层面,把目标系统拔高一层进行演绎。在具体与抽象之间,不断的推敲,找到合理的对现实的抽象描述。
这个分析推演的过程,就是寻找事物本质的过程。只不过,我们的日常工作,面对大量繁杂的需求,没有过多的时间进行设计层面的思考。现实,把我们磨成了需求翻译机器。
大部分程序员其实不甘于此,所以,我想通过一份教程,帮助有意愿寻求改变的同学,促进这种改变的达成。
2014年,我编写了目前公司使用的框架,已经稳定运行超过5年,支撑了超过60万行业务代码,但它自身只有6000行代码。接下来一段时间,我会以它为蓝本,站在重新编写一个框架的角度上,全面的复现编写框架的思考、分析、设计、实现整个过程,并将其整理为一份视频教程,以期能帮助大家寻找到程序设计的感觉。(自愿付费,可自由分享与传播)
整个教程大致分12讲,每讲有一个独立的主题,每讲时间1-3小时不等,并配以一篇公众号文章发布。大的层面框架分为3个部分:与外部环境的交互、对业务层的封装约束、ORM之类的辅助工具。
因文字表现力有限,本文仅作为一个引子,具体关于职业发展的分析、教程想要传递的价值、以及传递价值采用的方法,请下载视频教程深入学习。
【十年一剑,透过框架理解抽象思维】是我录制的一套系列教程,通过重现开发一套框架的思考、分析、设计、实现全过程,帮助大家寻找程序设计的灵感(自愿付费,可自由传播分享)。教程会通过公众号《抽象思维》发布。
今天发布的是第一讲《录制教程的意义》,感兴趣想要深入学习的同学,请扫码下载视频教程(地址: https://pan.baidu.com/wap/init?surl=IZ24Az5GFpQoQSD4WbfR8g 提取密码:rcga)
以上是程序员,你还能干几年?的详细内容。更多信息请关注PHP中文网其他相关文章!