又是一个周末,又是晚睡晚起,早饭随便吃一点,总说着要注意休息,但总不当回事。

在此立一个flag,从今天起,如果不是特别紧急的事情,哪怕留到明天去做,我也一定要早点睡觉!!!

每天要做

  • 晚上十点前准时上床睡觉,早上六点起床。

  • 坚持吃早饭,鸡蛋牛奶蔬菜面包水果玉米糊糊都行,吃六分饱即可。

  • 上班骑车,或走路,锻炼身体,公司离住处很近,所以不要太急,过马路看红绿灯,礼让行人。

  • 早上坚持练习英语口语,背记英语单词。

  • 到了工作时间,先把工作上的事情做完,再做其他的。

  • 中午保证半小时的睡眠时间,不玩手机。

  • 完成一个LeetCode上的编程题。

  • 出门前对自己一个微笑。

  • 写日记。

每周要做

  • 去健身房锻炼身体三次,跑步,肌肉练习均可。

  • 至少完成一个ARTS。

  • 和家里人打电话,对他们说我很好;和伶儿通个电话,并告诉她我很想你。

  • 去吃点好吃的,见一见朋友,放松身心。

每月要做

  • 做总结。

  • 读完一本科普或小说。

每年要做

  • 去一个自己从没去过的地方。

  • 回家陪父母聊聊天。

这一周,我提前一天完成了我的任务,用Golang给视频转码写了个小工具,复习了二进制基础,文件操作和Golang基本语法。

下午,一位朋友and他女友来看我,一起吃了顿冒菜,让我这平淡的周末多了份意料之外的喜悦。

亲爱的,你怎么不在我身边

距离上次会合已经过去一个月,却让我感觉如昨日。

想起我们一起看过日出,站在塔里木大桥上看日落,在乌鲁木齐大冬天跑出去看电影吃麻辣小龙虾,去西安吃酿皮和肉夹馍,到成都看熊猫。

可是,这个周末,亲爱的你为什么不在我身边。

当你孤单时你会想起谁

想起远在乌鲁木齐的父母,从此养成了报喜不报忧的“好习惯”;

想起远在厦门的凡儿,没事调侃两句,解解闷;

想起远在家里蹲的羊纪元,吹吹牛释放下压力;

想起远在西安做销售的魁拔,高中时教我弹吉他和护肤,在QQ炫舞上一同唱着《老男孩》;

我要你在我身旁

你说你毕设答辩结束就坐飞机来成都,我想起去年我也说,我答完辩把论文材料提交完毕立马坐最近的一趟飞机去成都找你,顺便把offer拿了。

现在过了一年,角色互换,我相信,我们的异地恋接近尾声。

我在成都等你。

题目描述

# [905] Sort Array By Parity
#
# https://leetcode.com/problems/sort-array-by-parity/description/
#
# Given an array A of non-negative integers, return an array consisting of all the even elements of A, followed by all the odd elements of A.
# 
# You may return any answer array that satisfies this condition.
# 
# Example 1:
# 
# 
# Input: [3,1,2,4]
# Output: [2,4,3,1]
# The outputs [4,2,3,1], [2,4,1,3], and [4,2,1,3] would also be accepted.
# 
# Note:
# 
# 1 <= A.length <= 5000
# 0 <= A[i] <= 5000
# 

解析

  • Python
class Solution(object):
    def sortArrayByParity(self, A):
        """
        :type A: List[int]
        :rtype: List[int]
        """
        i, j = 0, len(A) - 1
        while i < j:
            if A[i] % 2 > A[j] % 2:
                A[i], A[j] = A[j], A[i] #互换

            if A[i] % 2 == 0: i += 1
            if A[j] % 2 == 1: j -= 1

        return A
  • C++
class Solution {
public:
    vector<int> sortArrayByParity(vector<int>& A) {
        int len = A.size()-1;
        for(int i = 0;i < len;i++){
            if(A[i] % 2 == 1)
                swap(A[i--],A[len--]);
        }
        return A;
    }
};

题目描述

 * [977] Squares of a Sorted Array
 *
 * https://leetcode.com/problems/squares-of-a-sorted-array/description/
 *
 * algorithms
 * Easy (73.76%)
 * Total Accepted:    23.7K
 * Total Submissions: 32.2K
 * Testcase Example:  '[-4,-1,0,3,10]'
 *
 * Given an array of integers A sorted in non-decreasing order, return an array
 * of the squares of each number, also in sorted non-decreasing order.
 * 
 * 
 * 
 * 
 * Example 1:
 * 
 * 
 * Input: [-4,-1,0,3,10]
 * Output: [0,1,9,16,100]
 * 
 * 
 * 
 * Example 2:
 * 
 * 
 * Input: [-7,-3,2,3,11]
 * Output: [4,9,9,49,121]
 * 
 * 
 * 
 * 
 * Note:
 * 
 * 
 * 1 <= A.length <= 10000
 * -10000 <= A[i] <= 10000
 * A is sorted in non-decreasing order.
 * 
 * 

解析

此题比较简单,意思就是对数组里的数字进行排序和开平方。代码如下

  • Java
class Solution {
    public int[] sortedSquares(int[] A) {
        for(int i = 0;i < A.length;i++)
        {
            A[i] = A[i] * A[i];  //对数组中每个数都平方
        }
        Arrays.sort(A);  //对数组进行排序
        return A;
    }
}
  • Python
class Solution:
    def sortedSquares(self, A: 'List[int]') -> 'List[int]':
        def f(x):
            return x*x
        return sorted(map(f,A))

开启刷题之路

加入了大佬创建的刷题圈,目标是一天一道LeetCode算法题,按专题刷,加油!

春节结束,放假归来,已在公司上班两天。

向公司行政部申请买了块8G台式机内存条,额头上又隐约在冒痘痘了,半年过去了,难道还没有适应南方的气候?

伶儿说她明天早上七点就到乌鲁木齐了,距离我们下次见面就是她在学校答辩完,五月底六月初的样子。下次重逢,不要再分开了好吗?

哈哈,突然觉得自己好矫情,说这些。

昨天浑身酸痛,什么也不想做。今天试着看了些技术书,看不进去里面的概念,试着刷了几道LeetCode关于数组的题目,收获还行。

又要开始程序化的生活了,早起-骑车-工作-看书-下班-玩/学习-睡觉,如此循环。

好想做一些白日梦骗自己几分钟,又感到幼稚。

乱七八糟的写了些话,记录放假归来后内心烦躁的情绪。

不管怎样,生活还得继续,世界还等着我创造奇迹。

写以此文,记录我这三天(1.30-2.1)的收获和感悟。

上周把一个定时删除的服务的版本提交了,本以为在过年前的一周基本没什么事了。然而部门老哥告诉我,之前我负责的一个流媒体服务还存在两处bug

  • 不支持多用户同时拉取视频流;

  • 不支持重新连接;

所以这周我又忙着修改bug,然而在前两天,我还是束手无策,找不到应对方案,一筹莫展。

到了第三天老哥带我一步步熟悉整体流程,细致到每个函数,每个入参,以及每个重要的代码。不断的提问,不断的思考,再不断的提出新的问题,时间过得飞快,我也饿得快。不过最终还是蛮开心的,通过这两处bug,让我重新回顾了流媒体服务的整体工作流程,以及Go语言中对goroutinechannel机制,印象最深的是以下两点:

管道中的<-

简单来说就是这样子的:接受者<-发送者。

然而中间会多个管道,所以我借用Go语言圣经中的三处例子做解释

ch <- x  // x作为发送者发送给管道
x = <-ch // 管道作为发送者发送数据给接受者x
<-ch  // 管道发送数据,没有接收者,丢弃,同时造成管道堵塞,等待接收者

所以我们可以具体化刚才说的发送接收流程,它应该为:接收者 <- 管道 <- 发送者。如果缺了接收者或发送者,都会造成管道堵塞。

互斥锁

举个例子

import "sync"

var (
mu sync.Mutex   // guards balance
balance int
)

func Deposit(amount int) {
    mu.Lock()
    balance = balance + amount
    mu.Unlock()
}

func Balance() int {
    mu.Lock()
    b := balance
    mu.Unlock()
    return b
}

先Lock锁住,再使用Unlock解锁。

如果Lock中再套一个Lock,就会造成死锁,需要将前一个Lock解开才行。

dlv调试流程

1,./dlv debug xxxx(程序名)  ##启动dlv调试

2,r(restart)  

3,c(continue)

4,b(break)   ##打断点,可以打函数名,也可以打文件下对应的行号

5,n(next)或s(step)  ##n按一次单步执行,后面只需一直按回车;遇到需要深究的函数按s进去查看
##如果碰到多线程,建议在线程内打个断点

6,bt(stack)  ##查看堆栈

7,frame  ##查看指定堆栈的内容

8,q(exit)     ##退出调试

收获

  • 接触一个新东西,除了保证理解了流程,还要对每个函数的作用,影响范围都要了然于胸才行;

  • 流程这东西,光知道不行,最好的办法是自己画个流程图出来,一步步跟着代码走;

  • IDE有时会因为环境参数或内在bug而报错,所以推荐使用dlv(针对go)和gbd进行调试;

  • 多对自己提几个为什么,有助于理解技术的本质;

  • 心态放平和,坦然接受bug和不足,耐心寻求突破。

最后附一组测试成功的图片^_^

题目描述

题目一:找出数组中重复的数字

在一个长度为n的数组里的所有数字都在0~n-1的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是重复的数字2或者3。

解决方案

1,先把输入的数组排序;

  • 从头到尾扫描排序后的数组。排序一个长度为n的数组需要O(nlogn)的时间。

2,利用哈希表;

3,根据数组下表找重复数字;(过程会在后面详细写出)

bool duplicate(int numbers[], int length, int* duplication)
{
    if(numbers == nullptr || length <= 0)
        return false;

    for(int i = 0; i < length; ++i)
    {
        if(numbers[i] < 0 || numbers[i] > length - 1)
            return false;
    }

    for(int i = 0; i < length; ++i)
    {
        while(numbers[i] != i)
        {
            if(numbers[i] == numbers[numbers[i]])
            {
                *duplication = numbers[i];
                return true;
            }

            // 交换numbers[i]和numbers[numbers[i]]        
            int temp = numbers[i];
            numbers[i] = numbers[temp];
            numbers[temp] = temp;
        }
    }

    return false;
}

考点

  • 对一维数组的理解。一维数组在内存中占据连续的空间,因此我们可以根据下标定位对应的元素。

  • 学会通过具体例子找出其中的规律。

本题源代码

2019年1月23日,我参加了公司的年会彩排+表演。

此次年会收获如下:

  • 成功站在舞池中央,C位出道!
  • 步伐放慢一点,脚印踩实一些。
  • 有激情,才能带动一批人。
  • 再多坚持一会儿。

今天在豆瓣上看到一篇文章,分享一下:高效学习成长的丰沃土壤长什么样

与知识付费的相识

记得是大二的时候,下载了得到app,打开后看到里面琳琅满目的付费专栏,内容主要涉及管理学,经济学,科技和做人做事,价格基本是199元/年,我说“好贵!学生党买不起。”

后来经不住app里对专栏的介绍,我买了下吴军的《硅谷来信》,想跟着专栏学习下大师的思考方式和处世之道。不得不说,大师思考问题的维度和方式的确与我们不一样,因此拓宽了我的知识面,于是在一年后,我又坚持订阅了他的《谷歌方法论》。

再到后来大学毕业,我做了和服务器开发和算法相关的工作,在工作中深深感受到基础知识的匮乏,这时候一款名叫极客时间的app映入眼帘,在这里我看了相关介绍,陆续订阅了《数据结构与算法之美》和《程序员的基础数学》两个专栏。

还有其他类似的知识付费栏目,比如简书的付费阅读原创小说最后30%的章节内容;GitChat;只是星球。

为什么需要付费

曾经我很纳闷,这些知识网上都可以找到的,为什么还需要知识付费呢?

我想主要原因有以下几个方面:

  • 作者辛辛苦苦写出来的,我们总要回馈一些财富出来;(20%)
  • 网上内容良莠不齐,而作者是一路走过来的,因此有经验,会帮你整理出来,让你少走弯路;(60%)
  • 对版权的一种保护;(20%)

所以归根结底,是我们对获取知识的途径比较匮乏,需要有个人(比如专栏作者)把自己的学习心得和经验共享出来,供需要的人吸收,那么问题又来了,你吸收的这些知识,就一定是正确且有用的吗?

正视焦虑

我是一个喜欢有成就感持续驱动学习的人,这种成就感不是满足于一群人对我说“大佬 666”,而是每解决一个bug或close一个issue,搞懂一个模块的功能或者比昨天对框架有了更深入的理解。

然而,当我逐渐在学习底层的时候,我就会愈发现知识的不足,例如并发编程的原理,常用算法的核心思想,模块功能类比上的失误,以及对协议的认知偏差等等,这时候我很想一步登天,例如狂刷CSAPP,算法,但此时我已经产生了知识焦虑,犯了欲速则不达的错误。

学会分辨正确但无用的知识

“学会分辨正确但无用的知识”——这时一位前辈给我提的建议。

现在,我终于明白了这句话的含义。

无用,其实绝大多数是因为自己没有经过深度思考,只是别人告诉你,有这么个知识,你可以拿来套用和当谈资。但是这个知识到底有什么用,在什么场合下适用,都是要经过自己思考和实践出来的。

一个小例子

我有位高中玩的很要好的朋友,我当时总会调侃他的英语,然而我很佩服他的数学,虽然我做的数学题比他多,周末还报了数学辅导班,但是每当考试时,他都比我考的高。

我私下请教他学习数学的方法,他说你做题只满足做对就行,却没有从出题人的角度思考这道题,而我做这道题只花了五分钟,想这道题背后的用意以及举一反三的过程却花了我45分钟的时间。

的确,他经过深度思考了,所以知识是他的,而我是花钱(买课外资料,报辅导班)买了别人的解题思路,走了个捷径,现在想想,其实是走了弯路。

关于知识焦虑的感触

  • 正视自己的焦虑,因为有焦虑,所以才有强烈的求知欲和学习的动力;

  • 集中自己的时间和注意力,对枯燥的原理和底层的知识,进行深度思考;

  • 对那种表面业务逻辑部分,花最少的时间把它做好,后面就抽更少的时间维护即可;

  • 从源头开始阅读,尽量获取第一手的资料;

  • 正视自己的不足,扎扎实实一步一个脚印坚持走下去;

GOOD LUCK !

题目描述

如下为类型CMyString的声明,请为该类型添加赋值运算符函数。

class CMyString
{
public:
    CMyString(char* pData = nullptr);
    CMyString(const CMystring &str);
    ~CMyString(void);

private:
    char* m_pData;
};

解析

关注点如下:

  • 是否把返回值的类型声明为该类型的引用,并在函数结束前返回实例自身的引用(*this)。
  • 是否把传入的参数的类型声明为常量引用。
  • 是否释放实例自身已有的内存。
  • 判断传入的参数和当前的实例(*this)是不是同一个实例。

Show Code

经典,初级解法

CMyString& CMyString::operator = (const CMyString &str)
{
    if(this == &str)
        return *this;  //返回实例自身的引用

    delete []m_pData;
    m_pData = nullptr;

    m_pData = new char[strlen(str.m_pData) + 1];
    strcpy(m_pData,str.m_pData);

    return *this;
}

考点

  • C++基础语法,如运算符函数、常量引用;
  • 对内存泄露的理解

本题源代码

参考资料

意外惊喜

这段时间有两个意外发生在我的身上

头条邀请

下午打开Gmail邮箱,意外发现了除了Medium的推送外,还夹带着一封头条后端开发岗的邀请…

写书邀请

除了面试邀请,还在前段时间在博客园上收到了一家北京出版社编辑发的写开发实战书籍的邀请。
(写书曾经想过写,但不是现在写,因为技术还没有积淀下来,写了也是浪费精力和纸张)

低调成长

想起两年前我大二,对于这样的邀请我是可望而不可即的,因为技术太渣,校招时四轮笔试做了一塌糊涂。
但是,当现在机会摆在我的面前时,我不禁想问下自己,现在接受真的合适吗?
最好的目前并不一定适合自己。
现在的还处于学习上升期阶段,除了在部门内负责流媒体服务外,还要学习网络,数据库和算法相关知识,需要巩固C/C++和Go语言编程;不断的接受一些有挑战性的任务,在踩坑和写Bug中茁壮成长。
我一直相信,只要自己坚持做一件认为对的事情,培养成一个习惯(例如写日记,早起晨练,学习),那么这就是个如蛹化蝶的过程,最终将会振翅飞翔。

工作

目前了解到的会涉及以下方面:

  • 流媒体服务
    以Go语言为主;熟练掌握TCP/IP,HTTP原理;常用的MySQL和Redis数据库用法。
  • 视音频编解码
    C/C++语言为主;
  • 图形图像
    C/C++语言,OpenGL;OpenCV。

业余安排

业余时间计划完成以下事情:

附加技能

  • 熟悉JavaScript,争取能完成一个在线简历模板;
  • 熟练Java语言,希望能接1-2个毕设赚些零花钱;
  • LeetCode每周一题;

阅读提升

  • 极客时间上的四个专栏(左耳听风,趣谈网络,数据结构算法,数学基础)研读;
  • 开始阅读大部头经典书籍,例如CSAPP和UNP,并认真完成章节的课后练习题;
  • Medium上争取两周内翻译一篇和自己学习工作相关的技术文章;
  • 每天半小时学习口语;

培养兴趣爱好

  • 学习下拍照摄影,争取给女友拍出美美的照片~
  • 继续在健身房练习街舞,希望今年可以练出托马斯回旋和大风车;

其他

  • 继续维护我的英语学习项目VocabularyMap,争取在九月底国庆前完成词根词汇的拓展并加上中文释义。
  • 继续坚持创作,幻想和思考。

自我介绍

大家好,我的网名叫不会飞的章鱼(Zoctopus Zhang),活跃在简书、豆瓣、博客园和Github上,之前在博客园上坚持写技术博客长达两年半,截止目前已发布了两百多篇文章共23万人+的访问量,同时在简书上写文章积累了有十二万余字。然而,我一直很想创建一个自己的Blog,记录一些平时工作和生活上的收获和心得。
今天这个愿望终于实现了,在此我很感谢我的好友冰水鉴心的远程帮助。

接下来准备做什么

我本科学的专业是计算机科学与技术,2018年6月毕业后在一家上市游戏公司做了三个月的游戏服务器开发,之后因工作原因转行,目前主要做流媒体服务和与视音频相关的图形图像。
我想把我在工作中的学习心得和生活上的感悟记录下来。

那么,现在就开始吧

我不知道这条路我会走多远,但我至今不后悔我做出的每一个选择。因为我知道:念念不忘,必有回响。