如何提高解决编程问题的能力
我们大多数人都听过同样的建议:要想成为更优秀的解决问题者,就需要解决更多的问题。但这种建议过于简单。要想精通任何技能,光靠重复练习是不够的,方法也同样重要。
此外,程序员听到“解决更多问题”的建议时,往往会认为“更多”意味着更快。我刚入行时也犯过这个错误。
陷入解决问题的恶性循环不利于学习和进步。起初,我总是匆匆解决一个问题,然后立刻投入到下一个问题中。但很快我就意识到这种方法的弊端:我过于注重数量,牺牲了质量,也错过了过程中许多重要的学习机会。
这并不是说重复不重要;重复很重要。然而,单靠重复并不能触及问题的核心。关键在于过程。
我对这个话题非常感兴趣:我想提高解决问题的能力,从而提升我的编程水平。所以,我在这里分享一下我的学习计划。当然,这其中少不了反复练习——但远不止这些。
1. 在各种平台上解决各种问题
“我刚开始学编程的时候,对 HackerRank 简直着迷,”我上过的一门 Python 课程的老师说道。虽然有自己喜欢的平台无可厚非,但不要局限于单一平台。原因很简单:你需要做好应对各种情况的准备。
我的目标之一是能够流畅地切换不同类型的问题和不同的平台。Interview Cake 上的题目与 Reuven Lerner 的《Python Workout》一书中的题目不同。同样,我发现 Lerner 的《Weekly Python Exercise》中的题目描述与 HackerRank 上的题目描述也不同。
我当然有自己的偏好。但是,我需要能够解决各种类型的问题。所以我正在使用各种平台和资源进行练习。
以下是一些例子:
- LeetCode
- 面试蛋糕
- 《破解编程面试》作者:盖尔·拉克曼·麦克道尔
- 运动
- Reuven Lerner 的Python 练习
- Reuven Lerner 的每周 Python 练习
每周日,当我制定下周计划时,我会从上述资源中挑选几个问题。我会仔细斟酌。例如,我会从 LeetCode 上选择一道关于二分查找的题目。然后,我会从 Reuven Lerner 的某本书中选择一道关于数据结构的题目。
这种做法让我不敢过于安逸。我不能依赖相同的数据结构或技术。我需要能够选择最合适的工具。我必须具备灵活应变的能力。
它也给我带来了挑战。这是因为我选择的问题都会把我逼到极限,心理学家安德斯·埃里克森称之为“刻意练习”的一个特点。
刻意练习的核心在于技能发展。埃里克森在他那本优秀的著作《巅峰》中解释说,这是一种全神贯注、有意识的努力,它能让你走出“舒适区”,以特定目标为中心,并且“需要付出接近最大努力”。
换句话说,你不是在敷衍了事地做那些轻松自然的事情。“刻意练习的标志,”埃里克森写道,“就是你尝试去做你做不到的事情。”
2. 交叉训练你的编程大脑
你经常会听到运动员将交叉训练融入日常训练中。例如,跑步运动员每周会进行一到两次自行车训练。这很有道理:通过交叉训练,运动员可以从不同的角度提升心肺功能。
我之前写过关于程序员交叉训练的文章。然而,这种方法的益处还有很多值得探讨的地方。就像运动员通过交叉训练来提高心肺功能一样,我也在通过交叉训练来提升我的心理素质。
我的交叉训练包括解决数学问题。我把解决编程问题的方法应用到数学问题上。同样的流程,不同的情境。
我目前这本数学书确实提供了上述的交叉训练益处。但它还有更多作用:它帮助我培养解决问题的直觉。
这一点很重要。我不想死记硬背数学公式或运算过程,我希望能够凭直觉知道何时使用它们。解决编程问题也是如此。
3. 从你的解决方案中学习
我们每个人在解决问题时都会遇到困难,都会犯错。我们会利用这些失败来帮助我们找到改进的方法。
很多时候,学习就此止步。一旦我们解决了问题,就急于继续前进。但千万别这么做。
数学家理查德·汉明认为,学习就应该从那时开始。
“我认为研究成功比研究失败更重要……犯错的方式有很多,而做对的事情却很少,研究成功更有效率,”汉明在他的著作《科学与工程的艺术》中写道。
“回顾过去”和研究成功经验的想法我之前也写过,值得再次提及。
我们总是听到“从失败中吸取教训”的说法。但汉明说得对:我们也能从成功中学到很多东西。
因此,我解决问题过程中最大的改变之一就是将汉明的理论付诸实践。我清楚地记得我第一次遇到链表问题时的情景,当时链表对我来说是一种全新的数据结构。解决问题后,我仔细研究了代码。我把解决方案复制到一个 Google 文档中,并用注释来解释代码。
我希望确保自己清楚地理解自己做了什么以及为什么这样做,原因很简单:这样我才能再次做到。
4. 获取反馈
觉察力可以成为一位极好的老师。
不要想当然地认为你的解决方案就完美无缺。要通过获取反馈来亲自验证。反馈是进步的关键因素,也是刻意练习的重要组成部分。
我通过两种方式获得反馈。
首先,在我完成一道题之后,我会研究其他人的解法。有时,像 LeetCode 和Cracking the Coding Interview这样的资源会提供答案。有时,我会找到其他程序员解决同一问题的解法。有时,我会同时使用这两种方法。
无论哪种方式,下一步都一样:我从解决方案的开头开始,用自己的话解释每一行代码。例如,我会推测程序员为什么选择这种特定的数据结构。然后,我会写一份简短的程序总结,以巩固我刚刚学到的核心概念或新方法。
用自己的语言解释一段复杂的代码,是检验你是否真正理解它的绝佳方法。此外,你还能练习另一项核心技能:阅读代码。
如果遇到我不熟悉的东西,我会去研究。我会把他们的代码和我的代码进行比较。我会学习、评估、分析。这是一个艰辛的过程,但我从中受益匪浅。
第二种获取反馈的方法是直接向其他程序员寻求帮助。视频通话有助于实时逐行调试代码。当然,提交 pull request 也很有用。
反馈是有道理的:要采纳!将所学付诸实践。
5. 保持一致性
现在我们来谈谈重复练习。解决问题是一种技能。和其他任何技能一样,它需要时间来培养。它不可能一蹴而就,也不是一个周末就能学会的。这就是为什么我每天都会抽出时间来解决问题。
对于这种日常练习,人们通常会有这样的反应:“要学的东西太多了。我不可能每天都花时间解决问题。”
我的回答有两点。首先,总会有更多东西需要学习,永远如此。
其次,编程在很大程度上就是解决问题。这是我们这门技艺的基石。它值得你每天投入时间和精力。但需要注意的是:务必让你的每日练习成为一种有意识的行为。
这是一门艺术
许多人将解决问题视为一门艺术。我恰好也赞同这种观点。解决问题的过程本身也同样如此。
本文概述的是我提升问题解决能力的方法。你的方法可能截然不同。关键在于:要有意识地进行练习。质量至关重要;要认真对待每一个问题。
程序员兼作家:amymhaddad.com | programmerspyramid.com | 我在推特上分享编程、学习和效率提升方面的内容@amymhaddad
原文发表于amymhaddad.com。
文章来源:https://dev.to/amymhaddad/how-to-get-better-at-solving-programming-problems-23j5