最重要的事情
需要持之以恒,以兴趣, 作以实际的工作要解决的问题为主导
最终的目的:
大幅度提高自己的核心竞争能力和提高自己的思维能力。 思维方式决定境界与能力. 也需要最大程度的暴露自己所有的不足,从而才能够更好的提高.
3个月计划
在3个月之内掌握所有的初级算法,明白应用的场景,也能够用一个清晰语言表达解释出来. 能够快速的识别和反映出一般的算法解决问题.
一周计划
每次只制作一周的计划. 然后每解完一道题就要整理博客一天. 要弄懂一道题目要比想象中的要难.
From 12/08/2019 to 12/15/2019
初级算法类别 | 题目名称 | 预期完成时间 | 实际完成时间 | 超时多少 | 自我完成质量评估 | Comments |
---|---|---|---|---|---|---|
Binary Tree 树 | 二叉树的最大深度 | 12/8/2019 | 12/8/2019 | C | ||
整理博客 | 12/9/2019 | 12/9/2019 | C | |||
Binary Tree 树 | 验证二叉搜索树 | 12/ 11/2019 | 12/12/2019 | 1 day | C + | |
整理博客 | 12/12/2019 | 12/12/2019 | C+ | 慢慢找到点感觉了 | ||
Array 数组 | 旋转数组 | 12/13/2019 | ||||
整理博客 | 12/14/2019 | |||||
Array 数组 | 两个数组的交集II | 12/16/2019 | ||||
整理博客 | 12/17/2019 |
目前的方法:
以力扣的初级算法题目为引导,对所有类似的算法题目都有一个大概整体的认识.
反馈的机制:
通过leetcode的反馈, 对自己的练习进行评价,并且进行博客的总结.
进行纠正:
确保自己能够完全掌握了初级算法的全部内容和自己能够通过口头语言的形式解释出来.
运用场景的思考:
( 学的很浅,自己不能够回答,故结合了一些其他人精髓) 知乎中的一些解释
算法就是速度 (代码走多少步)和 内存( 有多少多余的步数)上面进行考虑. 例如二分查找要比有序查找要快很多. 有序查找为Big(n) 而二分查找为Big(logN) . 在二分查找这样的条件下面,我们在有序数组10000个值里面,要查找到我们的值,也只需要14步就行了, 这样就可以大量的节约我们的时间,从而达到我们想要的效果.
我们什么时候要考虑在代码里面加入这个思想?
在插入、删除、查找、遍历等操作都相对快的容器,于是人们发明了二叉树.
Recursion 是 Binary Tree里面的一环,这个基础要掌握. 如果对于Recursion 没有一个很好的理解的话,就很难能够理解这道题目的解法.
def getSum(n):
if (n == 1):
return 1
else:
return n* getSum(n-1)
缺点:占用大量的计算时间
优点: 写出来的代码好看,干净…
…
求MaxDepth
例如如何找到一个list [1,3,7,8,9,2] 的maxDepth ?
'leetcode 运用来迭代iteration的方式,'
class Solution:
def maxDepth(self, root):
"""
:type root: TreeNode
:rtype: int
"""
if root is None:
return 0
else:
left_height = self.maxDepth(root.left) # 在这里也就是说,我们的left是有一个值的. 当我们run这个function的时候,我们总是能够得到一个相应的值出来. 而且如何随着深度的扩大,他的值也会不断的扩大.
right_height = self.maxDepth(root.right)
return max(left_height, right_height) + 1
# max( self.maxDepth(root.left), self.maxDepth(root.right))
作者:LeetCode
链接:https://leetcode-cn.com/problems/maximum-depth-of-binary-tree/solution/er-cha-shu-de-zui-da-shen-du-by-leetcode/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
到底是如何通过max 这样的一个功能,实现了所有的逻辑。要完全理解这里. 我们就一定要利用Debug和手写同时进行来解决这道题目.
解答的关键就在下面:
left_height = self.maxDepth(root.left) 这个代码每次运行的时候,都会进行一个函数叠加, 例如 self.maxDepth(self.maxDepth(self.maxDepth(self.maxDepth(root.left) ) ) )
Validate Binary Search Tree
Assume a BST is defined as follows:
The left subtree of a node contains only nodes with keys less than the node’s key.
The right subtree of a node contains only nodes with keys greater than the node’s key.
Both the left and right subtrees must also be binary search trees.
个人小结: Leetcode上面的题目就像是高中时候做的理综和数学. 里面需要非常扎实的知识才能够进行更加有效的思考.
Leetcode里面解题的关键是找到left node 的最大边界值. Right node 的最小边界值. 如果Left node中有任何的值都要比最大边界值大,我们就必须判断这个tree是invalid的. 如果right node 中有任何的值都要比最小的边界值小就判断这个tree是invalid的. 这种形式的思维方式就是让我们跳出局限形式的思考. 而是站在一个更高的角度进行思考和提升.
这种边界值的思考方式其实经常运用在我们日常的开发工作中。当我们开发一个function的时候,我们就会思考这个function的边界值在哪里. 因为只有这样,我们才能够今早的防止我们的应用在之后的运行当中出现crash的问题. 我们要知道之后的维护成本要比之前的开发的成本大很多.
这道题对于我的启发而言就是, 不仅要在function里面去思考解决问题的思路,有的时候也要站在全局的方向上面去思考. 从而能够尽可能的找到更好的解决方式. 我们的大脑需要不同的思维方式来帮助我们更加高效的解决问题. 并且递归的思想是真的会让整个代码看起来much clearn and efficient.
下面我来先贴出leetcode的解法来进行分析. 需要进行更多的分析来理解.
# Definition for a binary tree node.
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
"""
作者:LeetCode
链接:https://leetcode-cn.com/problems/validate-binary-search-tree/solution/yan-zheng-er-cha-sou-suo-shu-by-leetcode/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
"""
class Solution:
def isValidBST(self, root):
"""
:type root: TreeNode
:rtype: bool
"""
def helper(node, lower = float('-inf'), upper = float('inf')):
if not node:
return True
val = node.val
if val <= lower or val >= upper:
return False
if not helper(node.right, val, upper):
return False
if not helper(node.left, lower, val):
return False
return True
return helper(root)
"""
作者:LeetCode
链接:https://leetcode-cn.com/problems/validate-binary-search-tree/solution/yan-zheng-er-cha-sou-suo-shu-by-leetcode/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
"""
下面是作者对于Leetcode 提供解法,又进行了一次解释. 从而可以帮助更好的理解. 看一遍解释并不意味着你下次就会写了. 这里面还需要更多的相关练习才行. Bruce Lee曾说过, 要先freestyle, you got know the basics, follow the all the instructions from the teacher, practice over and over, and reach the level of freestyle.
class Solution:
def isValidBSTSolved(self, root):
"""
:type root: TreeNode
:rtype: bool
"""
def helper(node, lower = float('-inf'), upper = float('inf')):
# 用recursion进行编程的话,要非常仔细的考虑整个循环的设计,从而代码能够
# 我们第一个要做的事情就是要思考处理Empty的情况.
if not node:
return True
# 然后决定我们的边界值/极限值, 之后要把starter node 拿到.
val = node.val
print("此时 lower and upper的 value 是: ", lower, ' ', upper)
# float('-inf') means negative infinite number and float('inf') means positive infinite number
# 我们设置 float('-inf'), float('inf') 就是为了帮助我们找到边界值.
if val <= lower or val >= upper:
# 这个部分是整个代码的核心. 就是我们在iterating the tree的时候,要不停的拿node的数值来和边界值进行对比. 从而作出我们的判断.
# loop的设计也要有一个轻重缓急. 要把最重要的放在最前面.
return False
if not helper(node.right, val, upper):
# 知识点的补充就是: if not 是 false --> true 的意思. 也就是说,当node.right没有值的时候,我们就有if not node == True的情况,然后我们就会跳出在右边loop的选择.
# 在第一个loop时候,我们选择是从整个tree的右边走. 然后我们选择进行递归recursion, 来决定我们的lower的值. 因为右边所有node的任何值都不能够比那个最小值还要小.
return False
if not helper(node.left, lower, val):
# 这边的loop就是在此时node的left node进行. 现在思考是node如何进行上移的.
return False
return True # 这个地方的应用也非常的巧妙, 因为我们return True的话, 我们的循环又会到helper 这个function 里面去. 而且当我们的function 拿到false的时候,我们就会跳出loop了.
return helper(root)