昨天面试被拒说我数据结构不行,于是拿起《数据结构与算法分析 java 语言描述第三版》打算啃.结果第一章的例子就把我搞晕了.题干是“打印输出正整数的每一位”,书里提供的解决思路如下: 考虑正整数 n=76234,首先需要打印 7623,然后再打印 4.而当 0<=n<10,则直接打印.于是根据递归的思想得到:
方法 1 void printf_Every(int num){ if (num >= 10){ printf_Every(num / 10); } printf(num % 10); }
认真考虑了递归的几个基本条件,怎么看都不满足有“基准情形”这一条. 百思不得其解.按照我的理解应该是这样:
方法 2 void printDigit(int n) { //基准情形 if(n<10) { System.out.print(n); } else { //不断推进 printDigit(n/10); System.out.print(n%10); } }
测试了也没问题.转头思考了一下,方法 2 能简化成方法 1.这才明白过来. 我就吐槽下书本能不能按照书本自身的标准解释循序渐进地讲解问题.不要一上来就各种简化版、阉割版. 对待新人太不友好了.
![]() | 1 xidaduo 2019-12-04 10:16:49 +08:00 ![]() ………………………………………………………………………………………………………………………………………… 这哪是简化阉割版?????????? |
![]() | 2 jackrebel 2019-12-04 10:19:18 +08:00 ![]() 我认识一个作者, 还算是畅销的。 他跟我说, 不要相信绝大部分作者, 他们都是从这里那里扣一点, 代码有时候凭脑子想的, 没有实践过, 有时间结论可能都是错的, 但是已经印刷出来了。。没办法。 哈哈哈。 |
![]() | 4 ayase252 2019-12-04 10:19:36 +08:00 ![]() .....在 if 外面就不算 base case 吗? |
![]() | 6 seki 2019-12-04 10:25:02 +08:00 对新人不友好和专业没什么关系。专业就是保证准确性的前提下,做到代码的简洁,直观等 |
![]() | 7 cmdOptionKana 2019-12-04 10:26:57 +08:00 ![]() 你的标题是“不专业”,你的结论是“对新人不友好”。牛头不搭马嘴。 |
![]() | 10 scukmh 2019-12-04 10:31:55 +08:00 不专业咋就和对新人不友好等同了。 |
![]() | 11 tdssssss 2019-12-04 10:32:55 +08:00 via Android ![]() 方法说的很清楚了,代码只是省去了 else 而已。。对比数学书里常见的“显然”“易证”,已经够友好了 |
![]() | 12 tonnycao 2019-12-04 10:35:44 +08:00 我记得原来看 structs2 的一本书,作者说他有意在编码的时候写错,就是让读者自己把代码调通,防止读者只抄代码不理解原理。 |
![]() | 13 inhzus 2019-12-04 10:36:17+08:00 via Android ![]() 就这?就这?就这? 点开标题前还以为又发现了什么写作 /翻译问题很多的书(比如我最近在看的多处理器编程的艺术,作者写的时候本来就比较晦涩,翻译的更是 shit ),感情就交换了下 if else 顺序就让你觉得不专业了? 今日热帖预订 |
![]() | 14 strive 2019-12-04 10:39:28 +08:00 没看出哪里不专业 |
![]() | 15 strive 2019-12-04 10:40:10 +08:00 反而方法一不用再进行重构,非常专业 |
![]() | 16 galaxy21 2019-12-04 10:40:23 +08:00 ![]() 看不懂不是因为你自己菜????? |
![]() | 17 Tumblr 2019-12-04 10:42:09 +08:00 感觉好麻烦…… 用 PowerShell 直接 $int.ToString().ToCharArray() |
![]() | 18 ipwx 2019-12-04 10:42:09 +08:00 via Android 可是,人家作者说不定真的第一反应写出来的是版本一,根本不是先写版本二再简化成版本一的呀? |
![]() | 19 lhx2008 2019-12-04 10:46:53 +08:00 via Android 你不如吐槽,明明是个迭代为什么要写成递归,浪费空间。所以别人写迭代就是装 B 用的。 |
![]() | 20 shintendo 2019-12-04 10:47:12 +08:00 基准情形就是在某些条件下不会调用自身,上面的代码把调用包在 if 里,不是完全符合吗?难道放 if 里认识放 else 就不认识了么…… |
![]() | 22 collery 2019-12-04 10:47:38 +08:00 我才学 C 语言写的就是第二版。看了重构后,写了第一版 |
23 jorneyr 2019-12-04 10:52:20 +08:00 ![]() @jackrebel 是的,最近畅销的 《漫画算法:小灰的算法之旅书籍》一书里的代码也是错误百出,很多都是编译不通过的。 |
![]() | 24 jaynos 2019-12-04 10:53:04 +08:00 我觉得可以多看看书再来吐槽作者没脑子还是自己菜 |
25 crazypig14 2019-12-04 10:54:12 +08:00 再体谅新人也逃不过菜是原罪啊 |
![]() | 26 zunceng 2019-12-04 11:00:25 +08:00 ![]() 面试官眼光独到。。。 |
![]() | 27 VoidChen 2019-12-04 11:01:34 +08:00 第一反应是转字符串循环一下就完事了。。 |
![]() | 28 jmc891205 2019-12-04 11:07:19 +08:00 建议看更专业的书籍:TAOCP 或者 CLRS (手动狗头 |
![]() | 29 l8g 2019-12-04 11:20:24 +08:00 看楼主过往回复也不是写代码的新手了,看了这个帖子感觉面试官看的还是挺准确的。。。 另外这种简单的东西为什么要用递归?误人子弟的书。 |
34 chickenJuicer 2019-12-04 11:46:21 +08:00 这不是挺专业的么, 书上要是写成你的那种写法才叫不够精简吧.. |
35 iyiluo 2019-12-04 11:47:00 +08:00 这不是一样的吗?基准情形不一定要放开头,有问题的是参数没校验,不过关注点不在那里可以理解。 |
![]() | 36 jasonyang9 2019-12-04 11:48:41 +08:00 这是再正常不过的递归实现了,自己人肉步进一下就知道它是满足“基准情形”的啊 |
![]() | 38 rioshikelong121 2019-12-04 12:11:56 +08:00 这个例子确实一般。 |
![]() | 39 xomix 2019-12-04 12:18:32 +08:00 ![]() 方法二的输出都是乱的,方法一可以很明白的解释什么是递归,递归做了什么,如何退出。方法二我看的脑仁疼。 |
![]() | 40 MisakaTang 2019-12-04 12:23:24 +08:00 递归终止条件写后面已经可以跟专业水平不过关挂钩了吗 ![]() |
![]() | 41 niming007zh 2019-12-04 12:37:06 +08:00 数据结构 不建议看那些著名的其实是垃圾的书,推荐看邓俊辉的 |
![]() | 42 lhx2008 2019-12-04 12:49:01 +08:00 via Android 其实吧,这本书序言就写的很清楚了,是给进阶用的,内容多书又薄,不适合自学。难度也比红皮那本大多了,建议楼主还是看算法第四版,每个细节都有讲解 |
![]() | 43 passerbytiny 2019-12-04 12:58:30 +08:00 @l8g 教人算法,和教人优化算法,是两本书。所以你也就过过“误人子弟的书”的嘴瘾,别人能出书。 |
![]() | 44 constexpr 2019-12-04 13:16:54 +08:00 via Android 如果把 ‘’ 直接 ‘’ 改为 ‘’只 ‘’, 这样就好理解了。他说的直接意思是不再递归了,只打印,而其他情形是都做。 |
45 jon 2019-12-04 13:51:12 +08:00 我怎么觉得第一段代码更好懂 |
![]() | 46 cominghome 2019-12-04 14:19:55 +08:00 我买过一堆工具书,有几本销量 top 的,内容还不如官方文档来得深入,甚至搜索引擎都比他讲得清楚。 |
47 YannLu 2019-12-04 14:23:13 +08:00 楼主幽默了,建议多看看代码规范或者如何写出优雅代码之类的书或文章,讲道理工作一两年后心里就应该有数了,上来就该写成方式 1 而不是写成 2 改成 1 |
48 yazinnnn 2019-12-04 14:27:21 +08:00 后序递归...... 楼主可以慢慢看,看到二叉树就明白了 |
49 NeezerGu 2019-12-04 14:47:27 +08:00 ![]() 的确第二段一看就懂, 但第一段看两遍也该懂了吧??? 他有什么特别难以理解的地方吗??? 如果有,没错,这就是编程的门槛,转行吧…… |
![]() | 50 misaka19000 2019-12-04 14:57:33 +08:00 via Android 菜就多练,吐槽书是不对的 |
![]() | 51 wutiantong 2019-12-04 15:07:01 +08:00 别吐槽了,好好学习吧。 |
![]() | 52 shfanzie 2019-12-04 15:07:56 +08:00 哈哈哈哈,原谅我不厚道的笑了。菜就多练,多看看别人规范代码是怎么写的 |
![]() | 53 winglight2016 2019-12-04 15:16:54 +08:00 这也能算问题?你不是数据结构不行,而是根本不懂 java 吧?或者完全没有编程概念? 不过,这个问题明明一句 print(String.valueOf(val))就好了,为什么需要递归? |
![]() | 54 Jrue0011 2019-12-04 15:54:06 +08:00 作者不是为了解这道题而用递归,而是在第一章为了简单介绍递归思想和设计法则举了这个例子,楼主应该把完整的段落发上来 |
![]() | 55 JerryCha 2019-12-04 16:10:37 +08:00 字里行间透露着这书没把话讲明白的感觉。 |
![]() | 56 hikarugo 2019-12-04 16:38:34 +08:00 我就说一句,你态度有问题。 一般人碰到这种情况是先自己思考为什么书上答案和我简单想到的不一致,是不是我考虑的不全面,而不是吐槽书本为什么出现的不是我想的。你这种想法很明显是碰到问题先不反思自己而是先去怪其他因素的思维方式。即使书本显示的写法 2,反之楼主想到写法 1,楼主是不是就会吐槽这本书好辣鸡啊,写的都是复杂版本,一点不优雅 |
57 edussx 2019-12-04 17:03:12 +08:00 https://en.wikipedia.org/wiki/Guard_(computer_science) 这种写法叫 Guard Clause,我 code review 的时候看到有人写多重嵌套 if 或者滥用 else 都会让他改写成这样 |
![]() | 58 KentY 2019-12-04 17:14:10 +08:00 LZ 这个问题跟书的质量关系不大. 但是中文技术书籍不管原创的还是翻译的, 质量差的是大多数. 有时候翻译的人本身都缺乏该领域的经验. 现在技术资源在网上都挺多的文章. 如果非要看书, 选择国外的原著经典书. 技术的英语很容易, 别上来就怵头, 看几章再说. 比翻译的强不知道多少. 举例一下, 20 多年前, 我读过机械出版社的 thinking in java. 这个都知道吧? 蓝绿封皮的, 翻译的烂的不行, 根本看不下去 还是花好像 80 来欧买了本原文. |
![]() | 59 rabbey912 2019-12-04 18:19:46 +08:00 楼主的算法基础好像也需要补一补 这种吐槽有点像初中生拿着高中生的教材说老师写得太难了 |
![]() | 60 shijingshijing 2019-12-04 19:40:17 +08:00 递归就应该按照第一种方法写,第二种编译的时生成的代码不如第一种精简,效率是否和第一种一样不好说,但无疑第一种是高效的。 |
![]() | 61 loryyang 2019-12-04 19:57:48 +08:00 我觉得这样的例子挺好的,促使读者思考,虽然作者文章不写,但是通过代码传授你更多的东西。至于看不看得懂,如果看不懂,放到编辑器里面 debug 一下肯定能懂。如果这点能动性都没有,那看书也学不到太多东西 |
![]() | 62 NotFoundEgg 2019-12-04 20:00:14 +08:00 专业的代码大都对新人不友好 你看各大框架的源码友好吗 过于友好就是冗余 否则为什么要学算法呢 还是提升自己吧 |
![]() | 63 secondwtq 2019-12-04 20:40:12 +08:00 @shijingshijing 以 code size 为理由不是很可取吧 ... |
64 Justin13 2019-12-04 20:50:48 +08:00 via Android 书上的更清晰,递归要么继续迭代,要么到达结束。很清晰,你的代码两个输出反而多余且难懂。 |
![]() | 65 shijingshijing 2019-12-04 22:48:58 +08:00 @secondwtq 编译器在处理的时候,printf(num % 10); 这一句无论什么条件下都会执行,可能会有优化。 现在的 CPU 都有 Branch Prediction,第一种写法个人感觉会有利于 CPU 进行优化。 以上纯属个人瞎猜的,具体还得看生成的汇编代码是什么样的,实际测试结果是什么样。 |
![]() | 66 silhouette 2019-12-05 00:18:25 +08:00 via Android 第一个更好理解啊,打印一个长串数字分成两步,第一步打印除最后一位外的所有高位,第二步打印最后一位。 |
![]() | 67 Kasumi20 2019-12-05 01:17:46 +08:00 via Android JS 一行代码搞定 n => n.toString().split("").forEach(it => console.log(it)) |
68 GeruzoniAnsasu 2019-12-05 01:58:21 +08:00 首先需要打印 7623,然后再打印 4 书的写法 先 print(76234/10) 再 print(4) 你的写法 System.out.print(n); //先看看能不能 print 4 printDigit(n/10); // 不能的话 print 7623 System.out.print(n%10);//最后 print4 “不专业!” 铪蛤蛤 |
![]() | 69 jxie0755 2019-12-05 02:55:46 +08:00 小同学, 你这........... 你要是这么说的话.............连我这个两年前才第一次 hello world 的人, 都要开始飘飘然的认为自己不算新人了................. |
70 exploreXin 2019-12-05 09:40:37 +08:00 这本书没读过,但是根据我读过的国外技术书籍的经验来看,老外都喜欢循序渐进的讲述知识,你看的只是第一章,坚持看下去很大肯能会有对前面章节算法的优化和深入讲解,当然也可能确实是作者功力不够,毕竟国外也是有东拼西凑出书赚钱的不良作者的嘛。 |
![]() | 71 sunziren 2019-12-05 10:14:37 +08:00 顶山去报复社会。 |
72 qingluo 2019-12-05 10:45:21 +08:00 从 sonar 这种静态代码分析工具的角度上来看,方法 1 会被警告,方法 2 要优一些。 最近在学习 scala 从 fp 的角度上来看 2 个都不好(不满足尾递归优化)。而且更 java 的方式难道不是应该是 int a = 1234567; Stream.of(String.valueOf(a)) .flatMap(s->s.chars().mapToObj(c-> (char) c)) .forEach(System.out::println); |
![]() | 73 l8g 2019-12-05 11:06:14 +08:00 @passerbytiny 别人能出书所以我就不能评价它不好?又是这种搞笑的理论。祝你以后买到的书看完之后都是五星好评。 |
![]() | 75 passerbytiny 2019-12-05 13:43:48 +08:00 @l8g #63 哦 |
![]() | 76 passerbytiny 2019-12-05 13:48:05 +08:00 A:所以你也就过过“误人子弟的书”的嘴瘾,别人能出书。(你比那个人差得远了) B:我比别人差得远,我就不能说别人误人子弟了? 提问:B 的脑回路为何如此奇特。 |