醉月思 发布的文章

单枪匹马与世界对饮

  最近有点丧,我不知道是否有受疫情大环境的影响。总觉得自己干什么都提不起劲来,有的时候非常明确的知道自己该做什么,但就是不愿意去做。就好似,无法避免失败,就为了逃避失败而选择沉沦了。。。我是一个非常骄傲的人,总觉得自己和别人不一样,但也说不出不一样的地方在哪里。亦或许这就是维护我自尊的唯一方式了吧。实话说,就目前来看,从出生到现在,过程并不惊艳,甚至都达不到优秀,勉强算个平淡无奇,未来也无卓越的可能性。也许是心理预期与个人表现不一致的差距,让我几乎每时每刻都承受着内心的谴责。从出生到小学,到中学,再到大学,到现在的毕业工作,似乎表现永远也不能让我及周围的人满意,周围人给我的评价就是各种懒,我自己却感觉深深的力不从心。

  很多时候,我会怀疑自我地幻想如果我生下来就是傻傻的该多好,这样我不管做什么,都能让我自己和别人满意。而事实却恰恰相反,家人们认为我很聪明,朋友们觉得我很厉害,我自己也以为我很牛逼。所以每当我看到别人优秀地方的时候,我一定需要给自己一个交代,我会试图找一个自己比TA更优秀的地方,如果这个点与TA的优秀点领域越接近,我心里便会轻松点。如此频繁的选择竞争性对手,让我一直活在谴责与鞭策相互交织的心理世界,这让我非常痛苦。我不知道这样的痛苦,何时会是一个尽头。但随着年龄的增长,这种痛苦越来越严重的侵蚀着我的意志。如同置身狂风骇浪,时刻不能停歇。

  或许每个人都这样,出生时感觉自己是世界的主角,到最后慢慢意识到自己是个跑龙套的,高估了自己被世界需要的可能性。好在大部分人拥有一种构建自我世界的能力,在某个学术领域,或是某种知识体系中,亦或许是某个社交圈,都能找到自己归属。我也在一直寻找着自己的归宿,无奈想要的太多,一直未能找到。

  我喜欢熬夜,自从高中熬夜看小说之后。白天,每个人都在奋笔疾书,我试图努力却总害怕。万一,我努力了,依旧比不过他们。那么,我又该怎样呢?一次又一次的因为害怕失败而选择沉沦。每当夜深人静,人们都停下脚步进入自己的梦乡之时,我便可以静静的享受夜的温柔,此时的我不用考虑如何竞争去超越别人,做任何事情都不用担心良心的谴责,只需好好享受属于自己的时光,幻想着岁月可期。

  我不会喝酒,也不喜欢喝酒,但我羡慕举杯邀明月的洒脱。我能在夜晚做到的最肆意的事,就是坐在电脑荧屏前,带上耳机听着个性电台推荐的DJ,指尖洋溢着代码的芬芳,跟随着音乐的律动,实现着无聊且好玩的想法,肆意妄为地浪费着大好时光,痛快!

5. Longest Palindromic Substring最长回文子串

解法1:中心拓展算法

思路

首先,我们知道回文串一定是对称的,所以我们可以选择一个对称中心,进行左右扩展,判断左右字符是否相等即可。
由于存在奇数的字符串和偶数的字符串,所以我们需要从一个字符开始扩展,或者从两个字符之间开始扩展,所以总共有 n+n-1 个中心。

实现代码

class Solution:
    def longestPalindrome(self, s: str) -> str:
        n = len(s)
        Max,sub = 0,s[0:1]
        for i in range(n):
            tmp = self.searchPalindrome(i-1,i+1,s)
            if len(tmp) > Max:
                Max = len(tmp)
                sub = tmp
            tmp = self.searchPalindrome(i-1,i,s)
            if len(tmp) > Max:
                Max = len(tmp)
                sub = tmp    
        return sub
    
    def searchPalindrome(self, left: int, right: int, s: str) -> int:
        sub = ""
        while left != -1 and right != len(s):
            if s[left] == s[right]:
                sub = s[left:right+1]
                left-=1
                right+=1
            else : break
        return sub

马拉车算法

class Solution:
    # Manacher 算法
    def longestPalindrome(self, s: str) -> str:
        # 特判 
        if len(s) < 2 or s == s[::-1]:
            return s

        # 得到预处理字符串
        t = "#" + "#".join(s) + "#"

        # 新字符串的长度
        t_len = len(t)

        # 数组 p 记录了扫描过的回文子串的信息
        p = [0]*t_len

        # 双指针,它们是一一对应的,须同时更新
        max_right = 0
        center = 0

        # 当前遍历的中心最大扩散步数,其值等于原始字符串的最长回文子串的长度
        max_len = 1
        # 原始字符串的最长回文子串的起始位置,与 max_len 必须同时更新
        start = 1

        for i in range(t_len):
            if i < max_right:
                mirror = 2 * center - i
                # 这一行代码是 Manacher 算法的关键所在,要结合图形来理解
                p[i] = min(max_right - i, p[mirror])

            # 下一次尝试扩散的左右起点,能扩散的步数直接加到 p[i] 中
            left = i - (1 + p[i])
            right = i + (1 + p[i])

            # left >= 0 and right < t_len 保证不越界
            # t[left] == t[right] 表示可以扩散 1 次
            while left >= 0 and right < t_len and t[left] == t[right]:
                p[i] += 1
                left -= 1
                right += 1

            # 根据 max_right 的定义,它是遍历过的 i 的 i + p[i] 的最大者
            # 如果 max_right 的值越大,进入上面 i < max_right 的判断的可能性就越大,这样就可以重复利用之前判断过的回文信息了
            if i + p[i] > max_right:
                # max_right 和 center 需要同时更新
                max_right = i + p[i]
                center = i

            if p[i] > max_len:
                # 记录最长回文子串的长度和相应它在原始字符串中的起点
                max_len = p[i]
                start = (i - max_len) // 2
        return s[start: start + max_len]

成果

2020-01-19T15:04:32.png

【leetcode】4. Median of Two Sorted Arrays寻找两个有序数组的中位数

我的初次实现

class Solution:
    def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
        newList = nums1 + nums2
        newList.sort()
        result = 0
        if(len(newList)%2 != 0) :
            result = newList[math.ceil(len(newList)/2-1)]
        else:
            index = int(len(newList)/2)
            result = (newList[index] + newList[index-1])/2
        return result

成果

2020-01-16T13:40:45.png

问题

但是我们仔细观察,可以发现这个的时间复杂度是不够的。

题目描述

思路

查找无重复的字符子串,然后滑动窗口

初次解

每次滑动一格窗口

class Solution:
    def isUnique(self, s: str) -> bool:
        for ch in s:
            if s.count(ch) > 1:
                return False
            else:
                continue
        return True
    def lengthOfLongestSubstring(self, s: str) -> int:
        i,j,Max=0,0,0
        j+=1
        while j <= len(s):
            if self.isUnique(s[i:j]):
                print(s[i:j],"is Unique",i,j)
                Max=max(j-i,Max)
                j+=1
            else:
                i+=1
        return Max

成果

第一次优化

class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        if(len(s)==1): 
            return 1
        i,j,Max=0,0,0
        while j <= len(s):
            st = s[i:j+1]
            if(j+1 < len(s)):
                index = st.find(s[j+1])
                if index > -1:
                    i+=(index+1)
                j+=1
                Max=max(j-i+1,Max)
            else:
                break
        return Max

成果

2020-01-15T07:27:31.png

【leetcode】2. Add Two Numbers两数相加

描述

给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。

如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。

您可以假设除了数字 0 之外,这两个数都不会以 0 开头。

示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807

思路

我看到这个题的第一感觉就是用递归把数获取出来,然后再相加,之后再把得数结构化。问题就被细分为了两个方面:

  1. 加数的提取
  2. 得数的结构化

我的初次实现

class Solution:
    def getStr(self,node: ListNode) -> str:
        if node.next == None:
            return node.val
        else:
            last = self.getStr(node.next)
            return  str(last) + str(node.val)

    def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
        num1 = self.getStr(l1)
        num2 = self.getStr(l2)
        result = int(num1) + int(num2)
        resultList = list(str(result))
        tmp = ListNode(int(resultList.pop(0)))
        List = tmp
        while resultList:
            tmp = ListNode(int(resultList.pop(0)))
            tmp.next = List
            List = tmp
        return List

成果

成果

改进思路

利用人列竖式算法的方法,计算每一列的值

改进代码

class Solution:
    def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
        # if l1.next == None and l1.val == 0:
        #    return l2
        # if l2.next == None and l2.val == 0:
        #    return l1
        l1_iter = l1
        l2_iter = l2
        Sum = l1_iter.val + l2_iter.val
        carry = 1 if Sum >= 10 else 0
        Sum %= 10
        List = ListNode(Sum)
        l1_iter = l1_iter.next
        l2_iter = l2_iter.next
        Site = List
        while(l1_iter != None and l2_iter != None):
            Sum = l1_iter.val + l2_iter.val + carry
            carry = 1 if Sum >= 10 else 0
            Sum %= 10
            tmp = ListNode(Sum)
            Site.next = tmp
            Site = Site.next
            l1_iter = l1_iter.next
            l2_iter = l2_iter.next
        last = Site
        if(l1_iter == None and l2_iter == None) :
            if(carry == 1):
                tmp = ListNode(carry)
                last.next = tmp
            return List
        else:
            Site = l1_iter if l2_iter == None else l2_iter
            tail = Site
            while(Site != None and carry == 1):
                Sum = Site.val + carry
                Site.val = Sum % 10
                carry = 0 if Sum < 10 else 1
                if(Site.next == None and carry == 1):
                    tmp = ListNode(carry)
                    Site.next = tmp
                    break
                Site = Site.next
            last.next = tail
        return List

成果

Add Two Numbers超越100%的Python用户

前言

在上篇文章中,我们已经实现了VS code的无缝连接docker,却依旧存在着一些问题。比如它需要安装pylint方便调试,但是每次stop 容器之后,重新启动又需要重新安装,不可谓不麻烦。而且我发现它也需要重新安装VS code server,这是一个严重影响生产力的过程。所以目前的需求就变了如何作一些自定义的修改,并让这些修改永久性的保存。那答案当然是自定义的构建镜像啦,它可以让我们在构建的实践使用容器的过程中,将所做的更新持续化保存到自定义镜像。

自定义修改

在这里,我手动做了两个修改,一个是安装pylint,一个是更新pip

自定义修改容器

提交更改

docker commit -m="install pylint" -a="chauncey" tf chauncey/tf 

如上命令,将所有对容器的操作都保存至自定义镜像chauncey/tf 中。

测试效果

  1. 停止当前容器
docker stop tf
  1. 使用自定义镜像创建容器
docker run --gpus all -itd --name tf --rm -v ~/Project:/root/Project  chauncey/tf  
  1. 使用VS code远程连接,观察pip版本和pylint的安装情况。

pip版本和pylint的安装情况

如上图,我们发现pip已经是最新的版本。而且细心小伙伴会发现,连接容器时以及没有了install Dev container的提示了,这说明我们的VS code也已经预设安装进了镜像。

为什么需要?

我们在上一篇Ubuntu深度学习的相关配置中最后讲到,将工作目录下的文件装载到了容器之下,这样我们在主机中编写一个文件,如tf.py。在容器中执行,需要输入以下命令。

docker exec tf python './tf.py' 

这样每改一下文件,想要看效果的话,就需要输入以上命令。而且,还不方便调试。然后,我就在想能不能做到像我平常写代码那样,在VScode中,点一下就运行,而且可以调试呢?于是便有了本文。

准备工作

  • 安装好VScode并且保证互联网连接正常。然后将工作目录装载到容器的/root/Project目录下,不然/tmp的文件实在是太乱七八糟了。
docker run --gpus all -itd --name tf --rm -v ~/Project:/root/Project  tensorflow/tensorflow:latest-gpu-py3

操作流程

首先安装两个插件dockerRemote Development

VScode的docker插件

上图中可以看到tensorflow的容器已经处于运行中了,然后再打开Remote Development

Remote Development

显示有一个容器待连接,然后选择它,打开容器中的Project文件夹

VScode in Container

然后安装Python插件和调试工具,修改tf.py文件

import tensorflow as tf
print("hello tensorflow")

点击右边的运行图标,成功输出。

run tensorflow

打开主机文件

docker主机文件同步

发现修改也已经同步,Over,现在可以愉快的写代码了。

使用 Docker 时需要首先下载一个官方镜像,例如 mysql、wordpress。然而由于网络原因,下载一个 Docker 官方镜像可能会需要很长的时间,甚至下载失败。为此,阿里云容器镜像服务提供了官方的镜像站点,从而加速官方镜像的下载。

登陆阿里云容器镜像服务

阿里云容器镜像服务
由上图可以看到,阿里给我们分配的专享加速域名。

配置docker源

针对Docker客户端版本大于 1.10.0 的用户

可以通过修改daemon配置文件/etc/docker/daemon.json来使用加速器

不过默认没有这个文件的,所以我们需要新建一个

新建daemon.json

sudo mkdir -p /etc/docker
sudo touch /etc/docker/daemon.json

设置源地址

{
    "registry-mirrors": ["<your accelerate address>"]
}            

重启生效

sudo systemctl daemon-reload
sudo systemctl restart docker            

Ubuntu使用阿里云加速docker pull
大功吿成!!

安装软件未满足依赖关系

安装软件curl时提示以下内容
下列软件包有未满足的依赖关系:
 curl : 依赖: libcurl4 (= 7.64.0-2ubuntu1.2) 但是 7.65.3-1ubuntu3 正要被安装
E: 无法修正错误,因为您要求某些软件包保持现状,就是它们破坏了软件包间的依赖关系。

这是由于版本不符的导致的,可能是以前卸载的时候未卸载干净。所以我们需要使用purge选项来重新卸载一次。

sudo apt-get purge libcurl4

然后重新安装,解决问题!!

Ubutnu安装软件未满足依赖关系

执行bash命令提示bash: /dev/fd/63: 没有那个文件或目录

bash: /dev/fd/63: 没有那个文件或目录

原因:<(…)运算符称为进程替换,是运行命令的一种方式,其输出进入匿名管道。这就是/dev/fd/63。其思想是允许外部命令(这里是bash)将另一个命令输出视为一个文件。通常形式是使用<将伪文件对象重定向到bash的输入流中。

解决方案,使用两个<code><</code>

解决方案,使用两个<

用户不在sudo列表

别问为什么出现这个问题,,,

解决方法

  1. 重启进恢复模式
  2. 选择root用户
  3. 添加用户至sudo组
adduser username sudo

系统没有设置图标

ubuntu没有设置.png

天哪,为啥我的电脑老是出现些奇怪的问题。

解决方法

  1. -sudo apt update-
  2. sudo apt install gnome-control-center

系统修复设置

tensorflow

安装NVIDIA驱动

  1. 查看显卡信息
ubuntu-drivers devices
  1. 自动安装显卡驱动
sudo ubuntu-drivers autoinstall
  1. 确认是否安装成功
nvidia-smi

安装docker

安装文档

使用阿里源安装

# step 1: 安装必要的一些系统工具
sudo apt-get update
sudo apt-get -y install apt-transport-https ca-certificates curl software-properties-common
# step 2: 安装GPG证书
curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
# Step 3: 写入软件源信息
sudo add-apt-repository "deb [arch=amd64] http://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"
# Step 4: 更新并安装Docker-CE
sudo apt-get -y update
sudo apt-get -y install docker-ce

# 安装指定版本的Docker-CE:
# Step 1: 查找Docker-CE的版本:
# apt-cache madison docker-ce
#   docker-ce | 17.03.1~ce-0~ubuntu-xenial | http://mirrors.aliyun.com/docker-ce/linux/ubuntu xenial/stable amd64 Packages
#   docker-ce | 17.03.0~ce-0~ubuntu-xenial | http://mirrors.aliyun.com/docker-ce/linux/ubuntu xenial/stable amd64 Packages
# Step 2: 安装指定版本的Docker-CE: (VERSION例如上面的17.03.1~ce-0~ubuntu-xenial)
# sudo apt-get -y install docker-ce=[VERSION]
tips: 由于使用的是19.10版本,暂时没有对应的源,故手动将step 3切换至19.04
sudo add-apt-repository "deb [arch=amd64] http://mirrors.aliyun.com/docker-ce/linux/ubuntu disco stable"

安装NVIDIA Container Toolkit

Add the package repositories

distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list
sudo apt-get update && sudo apt-get install -y nvidia-container-toolkit
sudo systemctl restart docker

测试

sudo docker run --gpus all -it --rm tensorflow/tensorflow:latest-gpu-py3    python -c "import tensorflow as tf; print(tf.reduce_sum(tf.random.normal([1000, 1000])))"

装载工作目录至容器

docker run --gpus all -itd --name tf --rm -v $PWD:/tmp -w /tmp tensorflow/tensorflow:latest-gpu-py3

以上命令在后台创建了一个支持GPU的tensorflow:latest-gpu-py3容器,将其命名为tf(方便后面容器操作),并将工作目录切换至主机当前目录。

装载工作目录至tensorflow容器

参考资料

Ubuntu 18.04 安装NVIDIA驱动 实践
tensorflow官网