分类目录归档:学习

《创业维艰》

 

概述

创业维艰》是今年来读过的印象较为深刻的书籍。

作者本·霍洛维茨作为硅谷投资教父级的任务,本身是一个成功的创业者,带领自己创业的LoudCloud公司活过了互联网泡沫破碎的时代,本人也是个成功的投资家,Facebook, Instagram, Twitter, Airbnb这些赫赫有名的公司都有他的手笔。

书中提到的一些观点个人读到之后觉得较为有趣,虽然并不身处于创业公司,但是读到之后个人还是引发了自己的思考,了解了创业这个方向的另一面。书中作者的措辞和举例的诚恳态度相当让人印象相当深刻。

成功者的经历几乎无法复制,但是成功者的经验却是可能会后来者规避更多陷阱的有效参考。

在Kindle上入了中信的译本,对自己觉得有意思的一些观点做简要的记录。

书摘

寻找一个统一市场,其中只要有一个投资者点头,即可成功。即便30位投资者即便全都摇头拒绝也无关紧要。

笔记:毕竟拥有十足信心的人在少数,即便是到了投资者这个级别,依然也有跟风的现象存在。

每当大公司打算事实一个计划时,该计划总会落到某个人身上,而此人却极有可能延误整个计划。如果此人是工程师,他也许会因为等待上层觉得而踌躇不前;如果此人是管理者,他也许会因为自己无权做出关键性购买决定而犹犹豫豫。这些看似微不足道的踌躇和犹豫很有可能会造成致命的延误

笔记:指令要明确,分工也需要具体,不能存在灰色地带。

大多数管理书籍的重点都是如何正确做事,不要把事情搞砸。但我的经验却是,把事情搞砸之后,如何深刻的理解你必须要做的那些事情。

笔记:然而很多时候个人代替从搞砸了事情中的吸取教训所做的事情却是悔恨与烦恼,并无用处。多人已经提过类似观点,戴尔也说过试错并学习(然而戴尔现在……)。

自己的员工要自己亲自辞退,不能将这项工作推给人力资源部门或某个更严厉的同事,不能像电影《在云端》中雇佣一家外包公司完成。

笔记:last day会被记住。

正确解雇高管的第一步是,搞清楚自己为什么为公司招错了人

如果这名高管是由董事会成员举荐而来的,打电话个人通知就显得尤为重要

说话要果断,不要给讨论留下悬念

向董事会宣布最新的人事变动信息时,一定要用积极正面的方式,不要给人一种“一脚将高管踢出公司的感觉”

此时,你也许会担心员工们曲解消息,以为公司陷入了困境。不要在意这些反应

笔记:不做评论,基本不会用到这些内容,但是最后一条让人对这类事件可以用一个新的角度去看待管理者们的表现。

人,尤其是那些创造事物的人,只愿意听好消息。

笔记:码农的天然乐观是个毒药,要学会接受坏消息。

不要花时间懊悔过去,要将所有时间花在自己可以做的事情上,因为说到底,没人会在意。

笔记:一针见血,懊悔过去当真是对当前的不负责,累计了更多的债务。再次强调,没人会在意自己做错的事情。

和平时期的世界与你每天必须为生活苦苦挣扎的世界完全不同。和平时期,人们有时间关注言行是否得体、长远的文化影响以及人们的情感这类问题。而在你为生活苦苦挣扎的时期,最重要的是奋勇杀敌,带领自己的队伍安全抵达目的地。

笔记:想起《鸿门宴》,沛公曰:“今者出,未辞也,为之奈何?”樊哙曰:“大行不顾细谨,大礼不辞小让。如今人方为刀俎,我为鱼肉,何辞为!”。活下去是第一要素。理解了某些情况下领导的做法。

我们要依次管理好人、产品和利润。

笔记:人生产产品,产品带来利润?

在科技公司里,一旦员工流失,就会出现螺旋式的循环:公司价值下跌,最优秀的员工流失,公司价值继续下跌,最优秀的员工继续流失。这种恶性循环很难逆转。

笔记:论公司的倒掉。

未完待续。

LeetCode-118-119-121-141-155

 

118 Pascal’s Triangle119 Pascal’s Triangle II121 Best Time to Buy and Sell Stock141 Linked List Cycle155 Min Stack 均较为简单,合并完成解题报告。

118 Pascal’s Triangle

概述

帕斯卡三角绘制。

分析

所谓帕斯卡三角,也叫做杨辉三角(也是贾宪三角……),解释可以在维基百科上得知。

那么只需按照定义,逐层生成即可。

解法

119 Pascal’s Triangle II

概述

只绘制杨辉三角的某行。

分析

属于118 Pascal’s Triangle的扩展题目,可以考虑直接复用118的代码,生成后返回。

问题在于时间复杂度过高。后续可以优化。

解法

121 Best Time to Buy and Sell Stock

概述

给出股价列表,找出最大的获利。

分析

可以想到,获利最大,即买入价最低,卖出价最高。

每个时间段都会有最高的卖出价,在数组中,一个区间的最大值是一定的。从后向前遍历,如果当前值不大于当前位置之后的最大值,那么当前值开始的最大值,仍然是当前值之后的最大值。反之则是当前值。

只需要针对价格,再次遍历数组,获得每个位置的数字的差值,即可知道在哪一位置时获利最大,即差值最大。

解法

141 Linked List Cycle

概述

判断单向链表中是否存在环。

分析

简单的做法,用hash存储当前的节点指针值,如果再次遇到这一指针,说明有环。

但是目前还没有做出不需要额外空间的做法。

解法

155 Min Stack

概述

用单向链表实现一个可以直接获得最小值的栈。

分析

栈的特点是先进后出。

push 操作,可以看做是更换首节点的操作。同时,由于要直接获得最小值,可以入栈时判断是否比当前的最小值更小,由此可以完成更新操作。

pop 操作,可以看做是删除首节点的操作。同样的,如果pop的数值比小于等于最小值,需要遍历链表找到最小值。

如是,随时获得栈最小值的时间复杂度是O(1)

解法

LeetCode-66-67-83-217

 

标题中提到的4道题目都较为简单,合并到一起写解题记录。

66 Plus One

概述

Plus One 即给定以数组形式表示各位的数字,将这一数字加1的结果输出为数组即可。

分析

这一题主要处理的是常规的运算的进位问题,同时,由于数组并没有确定数字为int,那么位数不定,需要按照正常的竖式运算的步骤进行。

当计算发现最高位需要进位时,申请更大的空间,返回结果。

解法

67 Add Binary

概述

Add Binary66 Plus One 很相似,只不过由十进制数变为了二进制数的加法。

输入是字符串,输出也是字符串。

分析

二进制加法,仍然按照竖式计算的方式进行即可。无需多说。

解法

83 Remove Duplicates from Sorted List

概述

Remove Duplicates from Sorted List 即在已排序的单向链表中完成去重。

分析

链表已排序,去重工作变得相当容易,只需要判断当前节点的值是否等于上一节点的值,如果等于则将链表当前的下一指针指向下下一个节点,周而复始。

解法

217 Contains Duplicate

概述

Contains Duplicate 判断数组中是否有重复的值。

分析

使用Hash完成这一判断最为容易,判断一个值是否在 HashMap 中存在即可。

解法

LeetCode-24-26-27

 

Swap Nodes in PairsRemove Duplicates from Sorted ArrayRemove Element 均为简单题,合并到一起写解题思路。

24 Swap Nodes in Pairs

概述

Swap Nodes in Pairs 即是将相邻的两个节点交换形成新的链表,要求在于不能修改值,只能做链表节点操作。

对于空间复杂度上也要要求,只能在 O(1) 这个复杂度上完成。

分析

对于链表操作,无需多说,这里需要注意的地方在于:

  • 第一组元素(前2个)的第二个节点需要变成新链表的首节点
  • 在循环中,前一组的第一个节点要连接的是下一组的第二个节点

明确上述两个关键步骤之后,需要做的就是申请变量暂存目前处理节点的位置以及记录上一组节点的第一个节点。

解法

26 Remove Duplicates from Sorted Array

概述

Remove Duplicates from Sorted Array 即通过数组元素移动操作,去除数组中重复的数字,并且返回不重复数字的个数。

分析

本题的需要注意,单纯返回非重复数字的长度是不够的,由于空间复杂度也有要求,需要在原数组中通过移位等操作将重复元素删除。

在是已经排序了的数组的情况下,相同数字必然是连续的,只需要遍历一遍数字,遇到相同的数字,将下一数字之后的数组元素前移即可。

下一次循环开始的

解法

27 Remove Element

概述

Remove Element 同样是remove,和26的区别是给定的数字进行去除。

分析

Remove Duplicates from Sorted Array 的解法类似,不同的是考虑终止条件的时候需要注意删除了元素之后相当于产生了一个数组,长度是发生了变化,循环时需要考虑这一因素。

解法

其他

26 与 27 逐个搬迁并不是最佳解法,还有优化的空间。

LeetCode-6

title: LeetCode-6

date: 2016-04-14 20:25:06

categories: Try

tags: LeetCode

概述

作为一道简单题,ZigZag Conversion 即将字符串按照之字形显示后,再逐行打印字符串。

分析

这一题题意自然是很明显的,但是,这个之字形的形状需要注意,这一个之字形的形状应该是:

A     G     M     S     Y
B   F H   L N   R T   X Z
C E   I K   O Q   U W
D     J     P     V

而不是类似字母 N 的模样。这里是需要注意的一点,题目中的示例为三行,并不是很明显。

简单来说,可以直接模拟重新排布字字母的过程,字母可以看做填写在一个 m * n 的矩阵中(m * n >= s.length())。

如果想要在 O(n) 的时间复杂度内解决问题,那么最理想的方法应该是根据行列的位置,确定当前是填充字母还是留空。

观察这一个矩阵,若行数为 n,那么可以看做有多个 n * (n - 1) 的子矩阵,形状都是重复的,只需要得到各个位置上的字符与源字符串中的下标的对应关系即可得知当前应该出现的字母。

对于一个行数为 n 的子矩阵,包含的字符个数应为 <= 2n – 2。从左往右,第 i 个(i >= 1)子矩阵的字符串包含的字母下标范围为 [(i - 1) * (2n - 2), i * (2n - 2))

从行的角度来看,每行在每个子矩阵中,子矩阵的第一列一定是有字母的,而这个字母在源字符串中正是连续的,所以,每行直接输出子矩阵对应的字母的前 n 个字符即可。

而剩下的 n – 2 个字符,则是类似斜率为1的一条直线的排布,我们要做的,即当运行到对应点时,结合横纵位置,判断当前是否有字符,如果没出现下标越界,说明此处应显示对应的字母。

解法

public class Solution {
    public String convert(String s, int numRows) {
        if (numRows == 1) {
            return s;
        }

        int sLen = s.length();
        int colNum = (int) Math.ceil(1.0 * sLen / numRows);
        int sectionNum = 2 * numRows - 2;

        String result = "";

        for (int r = 0; r < numRows; ++r) {
            for (int c = 0; c < colNum; ++c) {
                int idx = c * sectionNum + r;

                if (idx < sLen) {
                    result += s.substring(idx, idx + 1);

                    if (r >= 1 && r <= numRows - 2) {
                        int idxAppend = (c + 1) * sectionNum - r;

                        if (idxAppend >= 0 && idxAppend < sLen) {
                            result += s.substring(idxAppend, idxAppend + 1);
                        }
                    }
                }
            }
        }

        return result;
    }
}