第 1 周 ARTS

一.Algorithm

题目 5. Longest Palindromic Substring

从给定的字符串中拿到最长的回文子字符串。

基本思路:

  • 1.开始的想法是遍历所有的子字符串,拿到最大长度的进行返回。用 Python 实现代码如下:
class Solution:
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """

        result = ""
        tmp = ""
        for index, element in enumerate(s):
            tmp += element
            if tmp == tmp[::-1] and len(tmp) > len(result):
                result = tmp
            for x in range(index+1, len(s)):
                tmp += s[x]
                if tmp == tmp[::-1] and len(tmp) > len(result):
                    result = tmp
            tmp = ""
        return result

通过后的性能很差(beats 6% = = !)

  • 2.第一版是从第一个字符开始,不断加后面的字符得到子串,这样会把所有的子串都遍历一遍。改进时首先想到的就是减少遍历的数量, 从最长子串开始遍历,当
    未遍历子串长度均小于当前结果时停止遍历,返回结果。
class Solution:
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        result = ""
        length = len(s)
        for index in range(0, length):
        	  # 未遍历子串长度要大于当前结果长度 	
            if length - index > len(result):
                i = length
                while i > index:
                    # 从最长子串开始遍历,未遍历子串长度大于结果长度
                    if i - index > len(result):
                        sub_str = s[index:i]
                        if len(sub_str) != 1 and sub_str == sub_str[::-1] and len(sub_str) > len(result):
                            result = sub_str
                    else:
                        break
                    i -= 1
            else:
                break
        if len(result) > 1:
            return result
        return s[0]

改进后的效率 beats 14%, 提升了 8%, 然鹅依旧挫 = = !

  • 3.第三版是看了 discuss 的一个实现,通过不断扩展子串的长度,来确定最长子串的起始位置和长度,然后截取子串即可,Python 实现代码如下:
class Solution:

    substring_start = 0
    substring_len = 0

    def longest_palindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        length = len(s)
        for i in range(0, length):
            self.extend_substring(s, i, i+1)
            self.extend_substring(s, i, i)

        return s[Solution.substring_start: Solution.substring_start+Solution.substring_len]

    def extend_substring(self, s, start, end):
		 
		 # 如果符合条件就扩大范围,知道找到符合条件的最大长度子串
        while start >= 0 and end < len(s) and s[start] == s[end]:
            start -= 1
            end += 1
        sub_start = start + 1
        sub_len = end - start - 1

        if sub_len > Solution.substring_len:
            Solution.substring_len = sub_len
            Solution.substring_start = sub_start

在操作的时候遇到一个问题, “cbbd” 字符串在 RUN CODE 测试时成功,但是提交时始终报错输出的是 “cbb”,暂时没找到原因,用 Java 实现的代码性能 beats 87%,证明该解法相对而言已经比较好了。

做题的时候,因为是自学过来的,期间并没有对数据结构、算法这些基础知识有足够的重视与学习,深刻感受到了自己算法功底的薄弱,对很多方法概念都不怎么了解,做题时也不容易找到思路。下面一年的务必对这些基础知识进行大量的补习,通过每周的 ARTS 和日常学习,补足短板。

二.Review

What is Object-Oriented Programming?

A Simple Explanation of OOP

本周读了两篇比较简单关于面向对象的文章,第一篇文章简单介绍了何为面向对象,继承和多态的概念和形式,迷面向对象中 “is a” 和 “has a” 两种关系。第二篇对于面向对象的发展做了简要介绍: 最开始所有的 code 写在一个文件中; 通过将相似代码进行封装抽取,编程范式演化为了过程式编程;随着代码的增大,人们又引入 module 对代码进行管理;但随着软件工程越来越大,面向对象的编程方法也被人发展、熟知。

面向对象不是凭空出现的,其可以看做是对 module 的拓展。但其也有以下几点不同:

  • 对象内部数据、状态对外部是隔离的
  • 对象比 module 粒度更细,更加的抽象
  • 对象是一个封装的单位,类比于计算机,有自己的内部状态和交互协议,给他发一个消息,它执行一个操作
  • 不同于 module,对象间可以继承,进而又引出了多态的概念

两篇文章侧重点不同,第一篇文章对面向对象的介绍较为详细,第二篇文章简单介绍了面向对象编程的由来。个人在学习过程中还是更喜欢读第二类的文章的,因为任何技术都不是凭空产生,都是演化而来的。从面向过程的编程到面向对象编程,从 虚拟化技术到 Linux Containers 到容器技术,对一个技术来源演化过程的了解会让自己对技术的掌握更加的深刻与全面。

三.Tip

本周分享个关于 git 合并 commit 的操作,有时候因为一些调试或者其他原因,导致 git commit 的频率和粒度比较杂乱,这个时候如果能把关联功能或者操作的 commit 合并为一个,那么以后在 review 代码时也会比较方便的阅读和查看变化的过程。

下面是基本命令, 通过该命令进入交互式界面, 可以看到我有两次 code review 的提交, 其实是对于同一个功能的,因此我希望合并两个 commit。

git rebase -i

  1 pick 31d15b4 code review
  2 pick a06196b code review
  3
  4 # Rebase defdb40..a06196b onto defdb40 (2 commands)
  5 #
  6 # Commands:
  7 # p, pick = use commit
  8 # r, reword = use commit, but edit the commit message
  9 # e, edit = use commit, but stop for amending
 10 # s, squash = use commit, but meld into previous commit
 11 # f, fixup = like "squash", but discard this commit's log message
 12 # x, exec = run command (the rest of the line) using shell
 13 # d, drop = remove commit
 14 #
 15 # These lines can be re-ordered; they are executed from top to bottom.
 16 #
 17 # If you remove a line here THAT COMMIT WILL BE LOST.
 18 #
 19 # However, if you remove everything, the rebase will be aborted.
 20 #
 21 # Note that empty commits are commented out

看下面的命令注释可以知道,pick 表示使用该 commit。如果要合并,可以使用 squash 或者 fixup,两个命令都是将 commit 合并到前一个 commit 中。两者的区别在于,squash 表示将该提交合并到前一个提交中,合并后需要再次编辑 commit message,而 fixup 不需要编辑,直接将当前 commit 的 message 废弃,使用之前的 commit message

# 修改保存需要编辑 commit message
  1 pick 31d15b4 code review
  2 squash a06196b code review
  
  or
  # 修改保存后不需要编辑commit message;a06196b 的 message 会被废弃掉
  1 pick 31d15b4 code review
  2 fixup a06196b code review

合并前的 commit log 如下:

commit 57ccebf4decfa498db662abb4a0f1dc606be1785
Author: zouyingjie <[email protected]>
Date:   Sat Jun 23 18:12:59 2018 +0800

    code review

commit ddf7734e5f59e8d83fcaaa4e14b8ed86cb71a588
Author: zouyingjie <[email protected]>
Date:   Sat Jun 23 18:12:10 2018 +0800

    code review

commit defdb405ab7864c1977abd5725beb065f3548969
Author: zouyingjie <[email protected]>
Date:   Sat Jun 23 00:22:56 2018 +0800

    update

commit 1ecc66bb00e43907307fa403958ee7c252541590
Author: zouyingjie <[email protected]>
Date:   Sat Jun 23 00:21:14 2018 +0800

    init
(END)

合并后最后两个 code review 就变为一个 commit 了,如下:

commit c54726bf39f3a692c1ca8f0007606eb6c3569017
Author: zouyingjie <[email protected]>
Date:   Sat Jun 23 18:12:10 2018 +0800

    code review

commit defdb405ab7864c1977abd5725beb065f3548969
Author: zouyingjie <[email protected]>
Date:   Sat Jun 23 00:22:56 2018 +0800

    update

commit 1ecc66bb00e43907307fa403958ee7c252541590
Author: zouyingjie <[email protected]>
Date:   Sat Jun 23 00:21:14 2018 +0800

    init
(END)

比较简单的一个技巧,不过对代码维护还是挺有帮助的,特别是我这种有时候靠 print 大法调试的人。

四.Share

作为软件从业人员,一个非常大的问题就是技术更新速度过快,如果不紧跟步伐很容易会被淘汰。不同于医学、法律等随着时间积累知识会越来越“值钱”的行业,IT 技术很多时候都是一种时效性的资产。
针对这个之前读到的 《程序员修炼之道》中提到的几点非常值得反复回味,书中提到要像搞投资一样来完善自己的知识体系:

  • 坚持投资 – 不断学习
  • 多元化投资 – 多元化学习,发展第二技能,保持多维度的竞争,编程,英语,写作,演讲。其他的如 产品、商业、市场、金融知识的涉猎。做到一超多强无弱点
  • 平衡风险 – 不要专注于一门方向和技术
  • 低买高卖 – 在一门技术早期投入进去,收益更高。比如早期的 IOS、现在的区块链技术

就技术发展而言,个人还比较倾向于程序员应该要拓展后端相关的知识栈。本人是从移动端转的后端,也涉猎过前端的开发。整体感觉,对于前端移动端,尤其是移动端,其编程工作往往都较多的局限在代码层面,只需要保证代码质量和软件的性能,总体工作就不会有太大的难度。而后端,其关注面则要拓展到整个系统。因为单机性能和容量永远不是无限的,就注定了我们的应用会往集群去发展,而一旦到分布式集群层面,就会引申出各种问题。集群的负载、监控、性能、部署等。因此后端需要学习的技术栈也远远要超过其他端的工程师,但由此带来的技术上的历练也会更加的深刻,在技术上也可以达到更高的高度。

发布了46 篇原创文章 · 获赞 21 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/Ahri_J/article/details/105395769
今日推荐