赶在Master的尾巴前开始刷题吧!

前言

又过去了一个学期。在这个本应该是第一个学期的第二个学期期间,自己从头上了一边Data Science的各项基础课,包括算法,概率论和统计推断,却一直没有在刷题上下功夫。新年新气象,2018年就从刷题开始好了。

准备工作

LeetCode的账号早就申请好了,自己也曾经考虑报一个九章算法的课程系统刷题,不过最后都胎死腹中。打开LeetCode的网站,初步目标是将Easy先行刷一遍,当遇到问题或者觉得刷不下去之后考虑上一个九章算法的培训班。

Reference

这里是复习记录,遇到问题和有想法的时候会在这里更新。


Week 1: 1/1/2018 - 1/7/2018

1. Two Sum (约用时1.5h)

Given an array of integers, return indices of the two numbers such that they add up to a specific target.

You may assume that each input would have exactly one solution, and you may not use the same element twice.

问题

  • 没有一个明确和清晰的分析方法,知道naive algorithm能实现O(n^2),也知道应该存在O(n)的算法,不过不能具体跟之前课上学到的对应起来。
  • 知道应该用hash table之后还去查了Python中的hash table,结果发现直接用dict就可以完成,对于python的库已经忘记的差不多了,需要从头过一遍。
  • 具体逻辑上推了3遍才出来,逻辑不够清晰,还是得熟能生巧。
  • 逻辑跑通了之后没有handle edge case: 第一个test case[3,2,4],6就是没有考虑3不可以重复出现。
  • 用了简单粗暴的方法直接筛掉所有的target/2之后发现nums是可以重复的。[3,3], 6就是,自己在建立dict的时候没有考虑重复的情况倒是return null。
  • 之后又用了个愚蠢的方法每次都重新建立一个sub-dict把当前的element删掉,在测试最后一个test case的时候RT没有过。
  • 最后决定在最前面判断edge case:如果nums存在2个一样的element且值为target/2,则直接return 这两个element的index,如果不是的话进入for loop判断。

感悟

  • 自己还是太naive,掉入了几乎所有的陷阱T_T 考虑问题的时候首先找到切入点(数据结构是怎样的,RT最好大概能到多少,为了达到最佳RT需要怎么设计Data Structure和Algorithm),然后把基本代码写出来,最后考虑edge case和hidden case。
  • 自己的方法是一次性将所有的element加入到dict中,可能会导致edge case的出现。如果每一步加一次的话可以有效避免。

附录:最终的code

twoSum.pytwoSum.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Solution:
    def twoSum(self, nums, target):
        my_dict = {item:index for index,item in enumerate(nums)} # Create dict with item:index key-pair.
        if target % 2 == 0 and nums.count(target/2) == 2: # Edge case: two identical elements with target/2 value?
            return [i for i,val in enumerate(nums) if val==target/2] # return list of indexes. See reference
        else:
            for index, item in enumerate(nums): # for all elements in the list, O(n) RT 
                seek_number = target-nums[index] # Get the seek number
                if seek_number != target/2 and seek_number in my_dict: # avoid the edge case
                    return [index, my_dict[seek_number]]
                    break

# reference: https://stackoverflow.com/questions/6294179/how-to-find-all-occurrences-of-an-element-in-a-list

附录:网上的code

twoSumRef.pytwoSumRef.py
1
2
3
4
5
6
7
8
9
10
11
class Solution:
    def twoSum(self, nums, target):
        d = {}
        for i, n in enumerate(nums):
            m = target - n
            if m in d:
                return [d[m], i]
            else:
                d[n] = i

  • 这段code好在首先建立了empty dict, 之后遍历nums的过程中计算当前和target的差,然后在d中寻找。因为d一开始是空的,所以不会出现相同数值撞上的情况。思路值得学习!

7. Reverse Integer (约用时:25min)

Given a 32-bit signed integer, reverse digits of an integer. Assume we are dealing with an environment which could only hold integers within the 32-bit signed integer range. For the purpose of this problem, assume that your function returns 0 when the reversed integer overflows.

问题

  • 这道题看起来不算很难,只要go over所有character的话无论如何O(log(n))的时间也能搞定,不过有一点特别恶心人的是有一个Note说的是如果检测到integer超过了32-bit的话需要return 0,这一点没有注意导致错了两次。而且这里用来做比较的不是2^32,而是2^31,这一点我还没有太想明白,要看一下答案。(想清楚了:因为输入值可能是负的,所以范围不是(0, 2^32-1) 而是(-2^31, 2^31-1)。)
  • 另外一点出现问题的是自己没有彻底想明白当数字为负数的时候具体前后两端的index如何调整,由于我们是从后向前数数,应该调整的是结尾的index而不是开头的index。
  • 之前自己误以为RT是O(n),其实真正的RT应该是O(log(n)),因为RT是跟n有多少位有关,不是具体数字的大小。

    感悟

  • 注意题目要求,虽然python3能自动handle long number,但是还是要注意,因为其他语言可能不能handle这种情况。

  • 刷题要注意最好做到一遍过,这两道题自己都有些图快没有完全分析清楚,导致没有一遍过。做事还是要仔细一些,毕竟面试的时候都是在白板上完成,没有试错的机会。

  • 还是要熟悉基本的syntax,至少熟练掌握python和R的,应对DS的面试和coding的面试都能做到游刃有余。

附录:最终的code

reverseInteger.pyreverseInteger.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution:
    def reverse(self, x):
        string_x = str(x)
        result = ''
        if string_x[0] == '-': # edge case: negative number
            result += string_x[0] # add the negative sign in front
            end_num = len(string_x)-1 # do not include the first characger
        else:
            end_num = len(string_x)
        for i in range(0, end_num):
            result += string_x[len(string_x)-i-1] # add the character to result int
        if abs(int(result)) < 2**31: # edge case: check whether interger exceeds 32-bit limit
            return int(result)
        else:
            return 0

附录:网上的code

reverseIntegerRef.pyreverseIntegerRef.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution:
    def reverse(self, x):
        if x == 0:
            return 0
        neg = 1
        if x < 0:
            neg, x = -1, -x
        reverse = 0
        while x > 0:
            reverse = reverse * 10 + x % 10
            x = x // 10
        reverse = reverse * neg
        if reverse < -(1 << 31) or reverse > (1 << 31) - 1:
            return 0
        return reverse
  • 这个方法跟用String如出一辙,只不过是用处理数字的方法将答案一位一位加上去了。虽然看起来更繁琐了但是更能让人看懂。

9. Palindrome Number (约用时:15min)

Determine whether an integer is a palindrome. Do this without extra space.

问题

  • 思路已经很清晰了,不过在细节上还是需要斟酌:变量名称一开始没有注意写错了,导致前两次submit的失败。注意细节!
  • 考虑到负数的情况了, 不过没想到这道题直接一棒子打死,所有负数无论如何都不算palindrome。需要在最前面加一个判断。之前自己以为偶数负数不算,还是想错了。

感悟

  • 熟读题目要求!仔细考虑为什么这么说而不是那么说。在onsite中对于细节的地方直接问考官。
  • Solution中有一个直接用built-in reverse的方法很有意思,要好好把manual搞一遍。

附录:最终的code

isPalindrome.pyisPalindrome.py
1
2
3
4
5
6
7
8
9
10
11
class Solution:
    def isPalindrome(self, x):
        if x < 0: # edge case: false for all negative number
            return False
        else:
            x = str(x) # cast it into string
            for i in range(0, len(x)//2): # loop from 0 to the mid-point
                if x[i] != x[len(x)-i-1]:
                    return False
            return True

附录:网上的code

isPalindromeRef.pyisPalindromeRef.py
1
2
3
4
5
6
7
class Solution:
    def isPalindrome(self, x):
        if(str(x)[::-1] == str(x)):
            return True
        else:
            return False

13. Roman to Integer (Skip)

Given a roman numeral, convert it to an integer. Input is guaranteed to be within the range from 1 to 3999.

自己从来没有完全搞清楚Roman Numeral到底如何计算……之前最多算到过20,这道题暂且搁置起来等回头再看。

14. Longest Common Prefix (15min)

Write a function to find the longest common prefix string amongst an array of strings.

问题

  • 没有注意Python中单引号和双引号的区别,以为跟R里面一样可以互换的,还是对Syntax不熟悉。
  • 没有考虑到edge case:万一给的是一个empty list应该直接return空字符串。 -目前自己的算法算是O(nlog(n))的,因为首先找到最短的字符串,最短字符串的长度应该是log(n)。然后一个for loop从0到这个长度,在for loop里面看是不是所有的字符串在这一位上都是这个相同的值,如果不是的话返回当前长度。

感悟

  • 看了一下答案,这道题有4种算法,在RT上面可以说基本一样,不过在Space complexity上他们能达到O(1),这一点比我的方法好了不少。我的方法应该是O(n)的空间(其实我的code稍微变换一下用Horizontal scanning的话也能达到O(1),不过看起来就没有这么整齐了)。今天先不往下接着刷题了,好好复习Python Syntax和搞清楚这道题。

附录:最终的code

longestCommonPrefix.pylongestCommonPrefix.py
1
2
3
4
5
6
7
8
9
10
11
`
class Solution:
    def longestCommonPrefix(self, strs):
        if strs == []: # edge case: empty list?
            return ""
        shortest_length = min(len(x) for x in strs) # length of the shortest string
        for i in range(0, shortest_length): # loop through
            char_list = [x[i] for x in strs] # character list for all strings at position i
            if char_list.count(char_list[0]) < len(strs): # the sum of the count is less than total number
                return strs[0][:i] # return upon the current length
        return strs[0][:shortest_length] # edge case: all of them are the same, return the shortest one

附录:网上的code

这道题一共有四种思路:

  • Horizontal scanning: 从前两个String开始比较,将比较的结果记录下来,再跟下一个继续比较。
  • Vertical scanning: 先从所有String的第一个字符开始比较,如果成功的话再比较第二个字符,以此类推。
  • Divide and conquer: 跟第一种方法大致相同,不过不是一个接一个比较,而是按照D&C的方式拆开比较,最后再合起来。
  • Binary search: 将最短的String找出来,按照BS的方法拆开substring然后看其它string有没有包括这个substring。
longestCommonPrefixRef.pylongestCommonPrefixRef.py
1
2
3
4
5
6
7
8
9
10
11
class Solution:
    def longestCommonPrefix(self, strs):
        if not strs:
            return ""
        shortest = min(strs,key=len)
        for i, ch in enumerate(shortest):
            for other in strs:
                if other[i] != ch:
                    return shortest[:i]
        return shortest

20. Valid Parentheses(20min)

Given a string containing just the characters ‘(’, ‘)’, ‘{’, ‘}’, ‘[’ and ‘]’, determine if the input string is valid.

问题

  • 这道题思考的时候再考虑用什么Data Structure花了一些功夫,后来认定Stack是最好的方法:因为无论如何变换,只要输入的是右括号要想成立其前面的一定是一个左括号。利用Stack的FILO可以直接追溯到最后一个插入的括号。不过自己对于Python的Data Structure还是不太熟练,还是查了一下如何实现Stack。
  • 另外,自己认为的语法有问题:不能直接用 is in来表示,应该有正确的方法,编辑完之后要查一下并记住了。

感悟

  • 这次还算是一次过感觉很高兴,不过最好是连test case都不用直接交掉。继续加油!

附录:最终的code

isValidParentheses.pyisValidParentheses.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Solution:
    def isValid(self, s):
        stack = []
        if s == '': # edge case: empty string
            return True
        else:
            for i in range(0, len(s)):
                if s[i] == '(' or s[i] == '{' or s[i] ==  '[': # append to stack for left parentheses
                    stack.append(s[i])
                else:
                    if stack == []: # edge case: empty stack when coming in a right parentheses
                        return False
                    elif s[i] == ')':
                        if stack.pop() != '(':
                            return False
                    elif s[i] == ']':
                        if stack.pop() != '[':
                            return False
                    elif s[i] == '}':
                        if stack.pop() != '{':
                            return False
            if stack == []: # if stack is empty
                    return True
            else:
                return False

附录:网上的code

isValidParenthesesRef.pyisValidParenthesesRef.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Solution:
    def isValid(self, s):
        stack = []
        dict = {"]":"[", "}":"{", ")":"("}
        for char in s:
            if char in dict.values():
                stack.append(char)
            elif char in dict.keys():
                if stack == [] or dict[char] != stack.pop():
                    return False
            else:
                return False
        return stack == []
  • 网上的code更灵活的应用了dict,另外for loop的设置也更好,整体上更加简洁。

21. Merge Two Sorted Lists (25min)

Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists.

问题

  • 对Python的class definition不熟悉,不知道如何运用singly-linked list添加删除
  • 自己写的判断过多过于麻烦了,周末再好好重新复习这道题,用真正linked list的方法写出来

感悟

附录:最终的code

mergeTwoLists.pymergeTwoLists.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def mergeTwoLists(self, l1, l2):
        result = []
        if l1 == None and l2 == None:
            return []
        else:
            while l1 != None and l2 != None:
                if l1.val >= l2.val:
                    result.append(l2.val)
                    l2 = l2.next
                else:
                    result.append(l1.val)
                    l1= l1.next
            if l1 == None:
                while l2 != None:
                    result.append(l2.val)
                    l2 = l2.next
            if l2 == None:
                while l1 != None:
                    result.append(l1.val)
                    l1 = l1.next
        return result

附录:网上的code

.py.py
1
2
3
class Solution:

26. Remove Duplicates from Sorted Array (30min)

Given a sorted array, remove the duplicates in-place such that each element appear only once and return the new length. Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.

问题

  • 首先这道题题目说明的不好,明明应该只用返回长度,但是例子和run出来的test都会显示unique element,这一度让我非常困惑。
  • 这道题要求是用O(1)的Space,也就限制了只能在List上做文章。我用的方法比较简单,需要注意的是上下届,因为可能连续出现若干个相同的element,所以当相同的情况时候只用减少上界,还需要用再下一个跟这个重复的进行对比。

感悟

附录:最终的code

removeDuplicates.pyremoveDuplicates.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution:
    def removeDuplicates(self, nums):
        start = 0 # lower limit
        end = len(nums) - 1 # upper limit
        if start >= end: # edge case: empty list or list with 1 element
            return end+1
        else:
            while start < end: # go over the unique part of the list
                if nums[start+1] == nums[start]:
                    temp = nums.pop(start+1) # pop up the replicated element
                    nums.append(temp) # append to the end
                    end-=1 # decrease the lower limit to avoid it
                else:
                    start+=1
        return end+1

附录:网上的code

removeDuplicates_ref.py.py
1
2
3
class Solution:

27. Remove Element (30min)

Given an array and a value, remove all instances of that value in-place and return the new length. Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.

问题

  • 这道题本来可以在5分钟内解决,结果拖了半个小时,一方面有题目描述不清的问题:跟上一道题一样,一会儿说是length一会儿说是unique elements,让我无所适从。其实最后问题还是出在了上下界上面:判断当前值是否相等的时候在相等的情况下不需要调节下标,因为如果相等的话会将当前值和末尾的值调换位置,而末尾的值调换到当前位置之后还需要再判断一次,所以不能调节下标。

感悟

  • edge case的判断还是要细心再细心!好好过脑子想想再写code,如果想明白的话code其实并不算难写,还是想清楚问题最重要。

附录:最终的code

removeElement.pyremoveElement.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution:
    def removeElement(self, nums, val):
        start = 0
        end = len(nums)
        if len(nums) == 0:
            return len(nums)
        else:
            while start < end:
                if nums[start] == val:
                    nums.append(nums.pop(start))
                    end-=1
                else:
                    start+=1
        return end

附录:网上的code

.py.py
1
2
3
class Solution:


Week 2: 1/8/2018 - 1/14/2018

28. Implement strStr() (50min)

问题

  • 这道题不难,但是却花了50分钟才算出来,应该归咎于一开始自己想的太简单了,而后来又想的太复杂了。一开始我以为可以直接通过stack解决,即一个一个character判断,如果相同的话则进行下一个字母,如果不同的话从头开始。我还自认为考虑到了edge case,即万一当前的字母和应该判断的字母不同却和开头字母相同该怎么办。不过关键问题是例如”mississippi”和”issip”这种情况,重合的不止一个字母,这时候我的方法就失效了。当我发现这个方法不成立的时候走向了另一个极端:我准备用Dynamic Programming去搞定,想了15分钟左右却没能找到一个很好的表示方法…最后我突然想到判断substring的话并没有那么复杂,考虑完edge case之后直接按照needle的长度从头到尾取一边substring就可以了。真是暗笑我自己的迂啊!
  • 另外一点还是edge case:我自以为考虑的很全面,不过还是漏了关键的一点。如何检验edge case也是一门功夫,要好好把握!

感悟

附录:最终的code

strStr.pystrStr.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Solution:
    def strStr(self, haystack, needle):
        if len(needle) == 0 or haystack == needle: # edge case: empty or identical needle
            return 0
        elif len(needle) > len(haystack): # edge case: if needle is longer than haystack
            return -1
        else:
            for i in range (0, len(haystack)-len(needle)+1): # total h-n+1 positions
                sub_haystack = haystack[i:i+len(needle)]
                if sub_haystack == needle:
                    return i
            return -1

附录:网上的code

strStr_ref.pystrStr.py
1
2
3
class Solution:

35. Search Insert Position (30min)

问题

  • 这道题一看就是用Binary Search,不过稍微有一个小变化:当查找不到的时候返回应该插入的地方,而这个给我造成了一些困难。Binary Search很好写,不过在这里有一些edge case要仔细考虑:当target比第一个element还要小或相等时可以直接调用返回0,不过当当前元素比最后一个element还要大的时候,返回的应该是总长度(元素数量加一),而如果当前元素跟最后一个元素相等的时候则返回的是位置(当前元素),我在这里犯了错误。

感悟

附录:最终的code

searchInsert.pysearchInsert.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Solution:
    def searchInsert(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        if len(nums) < 1: # edge case: empty list
            return 0
        elif nums[0] >= target: # edge case: smaller than the first element
            return 0
        elif nums[len(nums)-1] < target: # edge case: larger than the last element
            return len(nums)
        elif nums[len(nums)-1] == target: # edge case same as the last element
            return len(nums)-1   
        else: 
            start = 0
            end = len(nums) - 1
            mid = (end + start) // 2
            while start != mid and mid != end: # could be changed to start != end
                if target == nums[mid]:
                    return mid
                elif target < nums[mid]: 
                    end = mid
                    mid = (end + start) // 2
                else:
                    start = mid
                    mid = (end + start) // 2
            return start+1

附录:网上的code

.py.py
1
2
3
class Solution:

38. Count and Say (skip)

看过Wiki之后大概了解了,不过这道题本身还是不太理解……先跳过了

53. Maximum Subarray (30min)

问题

  • 一开始打算用Dynamic Programming来做,不过却选择了2d array,其实如果这么做的话就不算是DP了,因为只是单纯的计算而已。如果用2d array的话RT只能是O(n^2),写完了之后发现Running Time Exceeded掉了,然后再次思考之后发现用1d array就可以解决掉。首先考虑有没有比O(n^2)更好的解决方法,然后要好好走心的思考!
  • 对于上下界还得再系统的总结学习一遍,老是出各种各样的问题也不太好。

感悟

附录:最终的code

maxSubArray.pymaxSubArray.py
1
2
3
4
5
6
7
8
9
10
11
class Solution:
    def maxSubArray(self, nums):
        if len(nums) < 1: # edge case: empty list
            return float("-inf")
        else:
            results = [nums[0]] # initiate results
            for i in range(1, len(nums)): # loop through 1 to the end
                results.append(max(results[i-1]+nums[i], nums[i])) # append the max between the continued subarray or start a new one
        return max(results) # return the max result

附录:网上的code

.py
1
2
3
class Solution:

58. Length of Last Word (10min)

问题

  • 总体来看比较简单,不过还是漏了一种edge case: 当string最后有空格的时候应该先把空格去掉,不然的话会直接return 0.

感悟

附录:最终的code

lengthOfLastWord.pylengthOfLastWord.py
1
2
3
4
5
6
7
8
9
10
11
class Solution:
    def lengthOfLastWord(self, s):
        length = 0
        s = s.strip() # delete whitespaces before and after
        for i in range(0, len(s)):
            if s[len(s)-i-1] != ' ': # whether the character is whitespace or not
                length+=1
            else:
                return length
        return length

附录:网上的code

.py.py
1
2
3
class Solution:

66. Plus One (10min)

问题

  • 这道题我的思路就是先把List of digits转化成integer然后加一,最后再转换回List of digits。这样可以避免很多edge case,比如需要进位等等。还是要注意写代码时候的细节。

感悟

附录:最终的code

plusOne.pyplusOne.py
1
2
3
4
5
6
7
8
class Solution:
    def plusOne(self, digits):
        number = 0
        for i in range(0, len(digits)):
            number += (digits[len(digits)-i-1]) * (10**i) # transform each digits into integer
        number += 1
        return [int(x) for x in str(number)] # return list of digits

附录:网上的code

.py
1
2
3
class Solution:

67. Add Binary (30min)

问题

  • 我的解法清晰明了:两个helper function负责转换binary和integer,然后直接调用helper function就可以了,需要注意log function的domain是positive real number,要考虑到edge case.
  • 在floor和ceiling上面花了点儿时间考虑:我想要的结果是转换为2进制之后有多少个digits,这里应该是往下取然后加一,好好理清逻辑关系。

感悟

附录:最终的code

addBinary.pyaddBinary.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Solution:
    def addBinary(self, a, b):
        import math
        def binary2Int(b):
            number = 0
            for i in range(0, len(b)):
                number += int(b[len(b)-i-1]) * (2**i) # same logic as 66
            return number
            
        def int2Binary(num):
            binary = ""
            digits = math.floor(math.log2(num)) + 1 # number of digits
            for i in range(0, digits): # for each digits
                if num >= 2**(digits-i-1): # if the num is larger than the current digits
                    num -= 2**(digits-i-1)
                    binary += "1"
                else:
                    binary += "0"
            return binary
                
        numA = binary2Int(a)
        numB = binary2Int(b)
        if numA == 0 and numB == 0:
            return "0"
        else:
            return int2Binary(numA+numB)

附录:网上的code

.py
1
2
3
class Solution:

69. Sqrt(x) (~50min)

问题

  • 这道题是刚开始刷题的时候做的, 如果用简单的从1开始一点点加上去的话会出现Time Limit Exceeded的情况,所以这里还是要用到Binary Search的方法。整体的RT应该能达到O(log(n))

感悟

附录:最终的code

mySqrt.pymySqrt.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Solution:
    def mySqrt(self, x):
        """
        :type x: int
        :rtype: int
        """
        start = 0
        end = x
        if x <= 1: # edge case: x = 0
            return x
        else:
            while(start <= end): # when start is not end
                mid = (start + end) // 2 # calculate mid
                if mid * mid > x: # if x < mid^2: decrease end
                    end = mid-1
                else:
                    if (mid+1) * (mid+1) > x: x is between mid^2 and (mid+1)^2
                        return mid
                    else: x < (mid+1)^2: increase start
                        start = mid+1

附录:网上的code

.py
1
2
3
class Solution:

70. Climbing Stairs (7min)

问题

  • 这道题是很经典的DP问题,在n时候的值是n-1加上n-2的值,有点儿像斐波那契数列的样子,不算很难,不过要考虑好edge case。

感悟

附录:最终的code

climbStairs.pyclimbStairs.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution:
    def climbStairs(self, n):
        if n == 0: edge case: n=0
            return 0
        elif n == 1: edge case: n=1
            return 1
        elif n == 2: edge case: n-2
            return 2
        else:
            list = []
            list.append(1)
            list.append(2)
            for i in range(2, n):
                list.append(list[i-1]+list[i-2]) 
            return list.pop()

附录:网上的code

.py
1
2
3
class Solution:

83. Remove Duplicates from Sorted List (15min)

问题

  • 由于上周周末没有完成总结,对于singly-linked list还是不太熟悉。这一次从头手写了一遍感觉好多了,要注意需要建立一个pointer作为指示,之前就是卡在了这里。
  • 另外,到了最后的时候要让这个pointer结束,用prev.next = None终结,这样才不会出现把后面的也给带上的情况。
  • Edge case还是要继续注意,要多考虑几种情况。

感悟

附录:最终的code

deleteDuplicates.pydeleteDuplicates.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def deleteDuplicates(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        if not head: # edge case: empty ListNode
            return []
        else:
            results = ListNode(head.val) # construct a new ListNode
            prev = results # setup pointer
            while head.next: # while there is a pointer to the next
                if head.next.val != head.val:
                    prev.next = head.next # let the pointer point the the item
                    prev = prev.next # move the pointer to the next
                head = head.next # move the list to the next in any cases
            prev.next = None # After finishing, close up the pointer
            return results

附录:网上的code

.py
1
2
3
class Solution:

88. Merge Sorted Array (~1h & TBD)

问题

  • 这道题很是气人:完全不知道为什么有4个input. 明明直接用2个就好了嘛,非得加上m和n. 我现在的问题是有一个testcase过不了,关键问题是这个testcase本身就是invalid的:题目非得说[0]的length是0,我认为这道题要不然说明是只排前n个和前m个,要不然就只用2个input。这纯粹属于脱了裤子放屁的行为,不理解!
  • 另外,我也不太清楚为什么网上的code就能修改nums1,而我的code在edge case这一步就完全不能修改,明明能print出来正确的值,但是却不能return正确的值,还是不理解!
  • 经过一番摸索,我大概理解了原因:因为这道题想让我们进行in-place的merge,所以nums1需要一些占位符去搞定。但是python其实并不需要这么操作,我准备再好好想想。回头要再把这道题好好过一遍。

感悟

附录:最终的code

merge.pymerge.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution:
    def merge(self, nums1, m, nums2, n):
        if m < len(nums1): # edge case:
            nums1 = nums1[:m]
        if n < len(nums2):
            nums2 = nums2[:n]
        if len(nums1) == 0:
            nums1[:n] = nums2[:n]
        else:
            insert_pos = 0
            lookup_pos = 0
            while lookup_pos < n:
                current_number = nums2[lookup_pos]
                if insert_pos == len(nums1):
                    nums1.insert(insert_pos, current_number)
                    lookup_pos += 1
                elif current_number < nums1[insert_pos]:
                    nums1.insert(insert_pos, current_number)
                    lookup_pos += 1
                insert_pos += 1

附录:网上的code

merge_ref.pymerge_ref.py
1
2
3
4
5
6
7
8
9
10
11
12
class Solution:
    def merge(self, nums1, m, nums2, n):
        while m > 0 and n > 0:
            if nums1[m-1] >= nums2[n-1]:
                nums1[m+n-1] = nums1[m-1]
                m -= 1
             else:
                nums1[m+n-1] = nums2[n-1]
                n -= 1
         if n > 0:
             nums1[:n] = nums2[:n]

100. Same Tree (25min)

问题

  • 这是我做到Binary Tree的第一题,稍微有些忘记了这方面的知识,一开始稍微走了些弯路。我的思路是用一个helper function去把Binary Tree转化成List,然后再对比List。这样有一个好处就是逻辑上更清晰了,不过就没有用更好的方法。
  • 如果是用我的方法的话有一个问题就是要保证同样的BT出来的List是一样的,不同的BT出来的List是不一样的。这里我在思路上用的是DFS,然后如果左侧或者右侧空了的话用字符串占位。
  • 有一个 更好的方法是采用类似recursion的方法,参见网上的code。这个写的特别精巧,我当时一度想考虑这个来着,不过算的不是很明白,要好好分析一下!

感悟

附录:最终的code

isSameTree.pyisSameTree.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def isSameTree(self, p, q):
        def tree2List(t):
            if not t: # edge case: empty node
                return None
            else:
                result = [] # string result
                stack = [t] # stack
                while stack: # if not finished
                    node = stack.pop(0) # pop the first element: FIFO
                    result.append(node.val) # append the value to the stack
                    if not (node.left or node.right): # if empty node
                        print("None")
                    else:
                        if node.left: # if there exists left node: add to stack
                            stack.append(node.left)
                        else: # add indicator to result
                            result.append("Left")
                        if node.right:
                            stack.append(node.right)
                        else:
                            result.append("Right")
                return result
        return tree2List(p) == tree2List(q)

附录:网上的code

isSameTree_ref.pyisSameTree_ref.py
1
2
3
4
5
6
7
8
9
10
class Solution:
    def isSameTree(self, p, q):
        if p is None and q is None: # if both p and q are empty nodes
            return True
        elif p is None or q is None: # if one of them are empty but not the others
            return False
        if p.val != q.val: # if value is not equal
            return False
        return self.isSameTree(p.left, q.left) and self.isSameTree(p.right, q.right) # use recursion to return the results from left node and from right node. Wonderful!

101. Symmetric Tree (1h & TBD)

问题

  • 这道题花了1个小时的时间去想,主要还是因为自己对Binary Tree的结构不熟悉,目前需要暂停做题先把Tree这一块好好复习一遍。
  • 这道题的答案非常巧妙:首先是recursion:其实这一点我也有想到,用recursion的话就是从同样的2个tree出发,如果二者下面的node位置一样的话,则返回3个判断的并集:value是否相等,左侧树的左支和右侧数的右枝是否相等,左侧树的右支和右侧数的左枝是否相等。这道题明天要再好好思考总结一番。

感悟

附录:最终的code

isSymmetric.pyisSymmetric.py
1
2
3
4
5
6
7
8
9
10
11
class Solution:
    def isSymmetric(self, root):
        def isMirror(leftT, rightT):
            if leftT == None and rightT == None: # two empty tree
                return True
            elif leftT == None or rightT == None: # either tree is empty
                return False
            else: # the value of current node, left of leftT vs. right of rightT, right of leftT vs. left of rightT
                return leftT.val == rightT.val and isMirror(leftT.left, rightT.right) and isMirror(leftT.right, rightT.left)
        return isMirror(root, root)

附录:网上的code

.py
1
2
3
class Solution:

Week 3: 1/15/2018 - 1/21/2018

155. Min Stack (30min)

问题

  • 这道题很明显要用stack,不过一开始没有想出来该如何保存minimum value。一开始我以为只要存储当前最小值就好,然后考虑到要是pop把最小值给pop出去了之后最小值会发生变换,思考了一会儿之后发现可以用2个stack来表示,一个是正常的stack,另外一个保存的是在当前位置时候的最小值。在push value进去的时候判断这个值是不是比目前最小值还要小,是的话则更新最小值,不是的话则保留原来的最小值。在pop value的时候将stack的值和min的值一起pop出去。

感悟

附录:最终的code

MinStack.pyMinStack.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
class MinStack:

    def __init__(self):
        """
        initialize your data structure here.
        """
        self.stack = [] # Initialize empty stack
        self.min = [] # Initialize empty min stack
        
    def push(self, x):
        """
        :type x: int
        :rtype: void
        """
        self.stack.append(x) # append x to stack
        if self.min == []: # edge case: empty min stack
            self.min.append(x)
        elif x < self.min[-1]: # if x is smaller than the min value
            self.min.append(x)
        else:
            self.min.append(self.min[-1]) # keep the current min value

    def pop(self):
        """
        :rtype: void
        """
        self.min.pop() # pop the value in min stack to release
        return self.stack.pop() # return the value

    def top(self):
        """
        :rtype: int
        """
        return self.stack[-1] # get the last item

    def getMin(self):
        """
        :rtype: int
        """
        if self.min is None: # edge case: empty stack
            return None
        else:
            return self.min[-1]

# Your MinStack object will be instantiated and called as such:
# obj = MinStack()
# obj.push(x)
# obj.pop()
# param_3 = obj.top()
# param_4 = obj.getMin()

附录:网上的code

.py
1
2
3
class Solution:

118. Pascal’s Triangle (15mins)

问题

  • 这道题还算比较简单,我首先观察了一下规律,然后选择用两个for loop去遍历所有的node,这道题最后的RT是O(n^2),我觉得应该是一个可以接受的结果。具体内容很清楚。

感悟

附录:最终的code

.py
1
2
3
class Solution:

附录:网上的code

generate.pygenerate.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Solution:
    def generate(self, numRows):
        """
        :type numRows: int
        :rtype: List[List[int]]
        """
        if numRows < 1: # edge case: 0 stage
            return []
        elif numRows == 1: # edge case: 1 stage
            return [[1]]
        elif numRows == 2: # edge case: 2 stages
            return [[1],[1,1]]
        else:
            results = [[1],[1,1]] # initialize 2 stages
            for i in range(2, numRows): # for loop for stages 2 to numRows
                temp = [1] # initialize current floor
                for j in range(1, i): # complete value in between
                    temp.append(results[i-1][j-1]+results[i-1][j]) # append the value
                temp.append(1) # append the last element
                results.append(temp) # append the finished floor to the stage
            return results

119. Pascal’s Triangle II (10min)

问题

  • 这道题和前面一道题思路差不多,不过这道题要求用O(k)的space去完成。具体思路跟前面一道题大同小异,用一个results去保存上一步的结果就可以了。不过还是要注意上下界和for loop。在后面的部分一开始没有注意indentation,导致应该在结尾才append 1的结果在每次计算之后都append 1了。做题还是要认真仔细一些。

感悟

附录:最终的code

getRow.pygetRow.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution:
    def getRow(self, rowIndex):
        """
        :type rowIndex: int
        :rtype: List[int]
        """
        if rowIndex < 1:
            return [1]
        elif rowIndex == 1:
            return [1,1]
        else:
            results = [1,1]
            for i in range(1, rowIndex):
                temp = [1]
                for j in range(1, i+1):
                    temp.append(results[j-1]+results[j])
                temp.append(1)
                results = temp
                print(results)
            return results

附录:网上的code

getRow.py
1
2

Week 4: 1/22/2018 - 1/28/2018

121. Best Time to Buy and Sell Stock (10min)

问题

  • 思路比较简单,只要记录当前最低值和当前最佳revenue的话就可以更新了。

感悟

附录:最终的code

maxProfit.pymaxProfit.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Solution:
    def maxProfit(self, prices):
        """
        :type prices: List[int]
        :rtype: int
        """
        if not prices: # edge case: empty list
            return 0
        else:
            revenue  = 0
            current_min = None
            for i in range(0, len(prices)):
                if current_min == None: # for first observation
                    current_min = prices[i]
                elif prices[i] < current_min: # update min_price
                    current_min = prices[i]
                if prices[i] - current_min > revenue: # update revenue
                    revenue = prices[i] - current_min
            return revenue

附录:网上的code

.py
1
2
3
class Solution:

122. Best Time to Buy and Sell Stock II (10min)

问题

  • 跟上一道题思路几乎完全一样,不同的是这次允许多次交易。在code上面的变化是如果current_min小于当前价格的话就交易并加上此笔交易的revenue,然后更新current_min为当前交易价格。通过这个方法在面对[1,2,3]的时候相当于是先买1卖2,再买2卖3,在最后的答案上跟买1卖3是一样的。

感悟

附录:最终的code

maxProfit.pymaxProfit.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution:
    def maxProfit(self, prices):
        """
        :type prices: List[int]
        :rtype: int
        """
        if not prices:
            return 0
        else:
            revenue = 0
            current_min = None
            for i in range(0, len(prices)):
                if current_min == None:
                    current_min = prices[i]
                elif prices[i] < current_min:
                    current_min = prices[i]                
                if prices[i] >= current_min:
                    revenue = revenue + prices[i] - current_min
                    current_min = prices[i]
            return revenue

附录:网上的code

.py
1
2
3
class Solution:

125. Valid Palindrome (15min)

问题

  • 逻辑上没有什么大的问题,不过题目中描写的不够好(其实是我的理解不对),alphanumeric characters指的是字母及数字字符,我以为只是字母,所以用了错误的function. isalnum()是检测alphanumeric characters, 而isalpha()是检测字母的。

感悟

附录:最终的code

isPalindrome.pyisPalindrome.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Solution:
    def isPalindrome(self, s):
        """
        :type s: str
        :rtype: bool
        """
        s = s.lower() # lower all letter
        if not s: # edge case: empty string
            return True
        else:
            i = 0 # start index
            j = len(s)-1 # end index
            while(i < j): # while not finished
                if not s[i].isalnum(): # edge case: char i is not a valid input
                    i+=1
                elif not s[j].isalnum(): # edge case: char j is not a valid input
                    j-=1
                elif s[j] != s[i]: # if two chars are not the same:
                    return False
                else: # if two chars are the same
                    i+=1
                    j-=1
            return True

附录:网上的code

.py
1
2
3
class Solution:

136. Single Number (20min)

问题

  • 这道题目不难,难的是在于如何实现Linear time和in-place。我通过dict实现了Linear time,不过没有实现in-place。这道题最好的思路是Bit Manipulation,是一个我不太了解的领域。附录答案如下。

感悟

附录:最终的code

.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution:
    def singleNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        dict_int = {} # empty dict
        for i in range(0, len(nums)): # loop through all elements
            if nums[i] not in dict_int: # if not seen before: add it
                dict_int.update({nums[i]: 1})
            else: # remove seen item
                del dict_int[nums[i]]
        for key in dict_int:
            return key

附录:网上的code

Concept

  • If we take XOR of zero and some bit, it will return that bit
    • a \oplus 0 = aa⊕0=a
  • If we take XOR of two same bits, it will return 0
    • a \oplus a = 0a⊕a=0
  • a \oplus b \oplus a = (a \oplus a) \oplus b = 0 \oplus b = ba⊕b⊕a=(a⊕a)⊕b=0⊕b=b

So we can XOR all bits together to find the unique number.

singleNumber.pysingleNumber.py
1
2
3
4
5
6
7
8
9
10
11
12
class Solution(object):
    def singleNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        a = 0
        for i in nums:
            a ^= i
        return a

141. Linked List Cycle (30min)

问题

  • 这道题我一开始也在想要不要用Hash Table做,不过这样就不能实现O(1)的space requirement了。在看过答案之后发现可以通过一个很巧妙的手段去实现:用2个pointer,一个快一个慢,如果没有cycle的情况下那么快的pointer每次前进2步,最终会到达结束,那么就说明这个linked list没有cycle。如果有cycle的话那么快的pointer会绕回去,然后最终会跟慢的pointer撞上。这个思路非常巧妙,2 pointer的方法有很多种,这一种让我学习到了不少。

感悟

附录:最终的code

hasCycle.pyhasCycle.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution(object):
    def hasCycle(self, head):
        """
        :type head: ListNode
        :rtype: bool
        """
        if head == None or head.next == None: # edge case: empty list or only 1 node in it
            return False
        else:
            slow = head # slow pointer
            fast = head.next # fast pointer
            while slow != fast: # if not equal
                if fast == None or fast.next == None: # if fast pointer reaches the end
                    return False
                slow = slow.next # move slow pointer 1 step forward
                fast = fast.next.next # move fast pointer 2 steps forward
            return True

附录:网上的code

.py.py
1
2
3
class Solution:

167. Two Sum II - Input array is sorted (20min)

问题

  • 这道题还是采用2 pointer的方法,因为这个list是从小到大已经排序好了的,所以有一个很巧妙的方法就是设置一前一后两个pointer,当这两个pointer指向的数字相加小于target的时候,把前一个pointer往后挪动1位,如果大于的话则把后一个pointer往前挪动一位。这样的话就可以去逼近那个值,直到找到对应的答案。

感悟

附录:最终的code

.py.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution(object):
    def twoSum(self, numbers, target):
        """
        :type numbers: List[int]
        :type target: int
        :rtype: List[int]
        """
        start = 0 # front pointer
        end = len(numbers)-1 # end pointer
        while start < end: # if start is less than end
            if numbers[start]+numbers[end] > target: # sum is greater than target: move back end pointer
                end-=1
            elif numbers[start]+numbers[end] < target: # sum is smaller than target: move forward front pointer
                start+=1
            else:
                return [start+1, end+1]

附录:网上的code

.py
1
2
3
class Solution:

168. Excel Sheet Column Title (40min)

问题

  • 这道题让我花了好久:主要原因是我一开始想的出现了些问题,我以为可以按照10进制的方法去做这道题,结果发现其实并不可以。然后我就调整思路,通过一步一步求对除26的余数,然后把结果除26来达成目标。

感悟

  • 这道题的感悟就是不能随随便便拍脑门,思考过程是必要的,而且是需要在写代码之前就基本考虑好的。

附录:最终的code

convertToTitle.pyconvertToTitle.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution(object):
    def convertToTitle(self, n):
        """
        :type n: int
        :rtype: str
        """
        if n < 1: # edge case: non-positive integer
            return ''
        else:
            colName = ''
            i = 1
            while n > 0:
                currentDigit = n % 26
                if currentDigit == 0:
                    currentDigit = 26
                colName = chr(currentDigit + 64) +  colName
                n = (n - currentDigit) / 26
            return colName

附录:网上的code

.py
1
2

169. Majority Element (10min)

问题

  • 没有什么大问题,直接用hash table达到linear time。答案中有另外一种方法还能实现in-place,要好好看一下。

感悟

附录:最终的code

majorityElement.pymajorityElement.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution(object):
    def majorityElement(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        totalNum = len(nums) # length of the nums
        numDict = {} # initialize dict
        for i in nums:
            if i not in numDict: # element that is not in the dict
                numDict.update({i: 1})
            else:
                numDict[i] += 1
            if numDict[i] > math.floor(totalNum/2): # check if it is the majoirity element
                return i

附录:网上的code

  • 这个的思路就是先initialize count, 然后当count是0的时候用当前的integer,如果当前的integer和candidate是一样的话则count加1,不然count减1。这个的绝妙之处在于无论数字如何分布,最后的结果都会是正确的。
majorityElement.pymajorityElement.py
1
2
3
4
5
6
7
8
9
10
11
12
class Solution:
    def majorityElement(self, nums):
        count = 0
        candidate = None

        for num in nums:
            if count == 0:
                candidate = num
            count += (1 if num == candidate else -1)
            
        return candidate

171. Excel Sheet Column Number (5min)

问题

  • 思路很简单,而且因为字母顺序和python的ord()一致,不需要额外再写东西。直接用一个简单的for loop累加上去就好了。

感悟

附录:最终的code

titleToNumber.pytitleToNumber.py
1
2
3
4
5
6
7
8
9
10
11
class Solution(object):
    def titleToNumber(self, s):
        """
        :type s: str
        :rtype: int
        """
        colNum = 0
        for i in range(0, len(s)):
            colNum += (ord(s[len(s)-i-1])-64) * 26 ** i # Simple calculation
        return colNum

附录:网上的code

.py
1
2

172. Factorial Trailing Zeroes (15min)

问题

  • 问题本身并不难,相当于是看有多少个能被5, 25, 125等5的级数整除的数,然后累加上去就好了。问题还是处在syntax上面:python的乘方是**而不是^!一定要清清楚楚的记住!

感悟

附录:最终的code

trailingZeroes.pytrailingZeroes.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution(object):
    def trailingZeroes(self, n):
        """
        :type n: int
        :rtype: int
        """
        if n < 5: # edge case: no zero
            return 0
        elif n == 5: # edge case: one zero
            return 1
        else:
            numOfZero = 0
            num = int(math.floor(math.log(n,5))) # max number of power of 5
            for i in range(1, num+1):
                numOfZero += n // 5**i # add the corresponding number of 5
        return(numOfZero)

附录:网上的code

.py
1
2

203. Remove Linked List Elements (20min)

问题

  • 这道题在思路上比较简单,但是在implementation上面遇到了一些edge case和困难。如果是empty list的话应该直接return [], 如list里面只有1个要去除的element的话则需要特殊考虑return []。除此之外,首先要确认第一个不是要去除的element的element并把这个确定为head,然后通过headPointer去找下一个。当headPointer.next不是None的时候判断下一个的值是不是要去除的值,如果是的话则跳过这个,如果不是的话需要让pointer前进。

感悟

附录:最终的code

removeElements.pyremoveElements.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution(object):
    def removeElements(self, head, val):
        """
        :type head: ListNode
        :type val: int
        :rtype: ListNode
        """
        if not head: # edge case: empty list
            return []
        else:
            headPointer = head # set up pointer
            while headPointer.val == val: # while the first element need to be deleted
                if headPointer.next == None: # edge case: only 1 element exists
                    return []
                else:
                    head = headPointer.next # update the head to the next
                    headPointer = head # update the pointer
            while headPointer != None: # while the pointer is not None
                if headPointer.next == None: # if the pointer is end: return the head
                    return head
                elif headPointer.next.val == val: # if the value of the next need to be deleted
                    headPointer.next = headPointer.next.next # update the pointer to be the second next one
                else:
                    headPointer = headPointer.next # update the pointer to the next element

附录:网上的code

.py
1
2

198. House Robber (20min)

问题

  • 这道题目是经典的DP问题,我打眼一看就知道应该怎么做。这道题的DP是在当前位置下的最佳选择。公式如下:DP[n] = max(DP[n-1], nums[n] + DP[n-2], 即当前位置的最佳选择是不偷这户和不偷前一户中的较大值。

感悟

附录:最终的code

rob.pyrob.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution(object):
    def rob(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        if not nums: # edge case: empty list
            return 0
        else:
            results = [0] # add a 0 in front
            results.append(nums[0]) # add the first household
            nums.insert(0,0) # insert 0 in front
            for i in range(2,len(nums)): # for the second household and then:
                results.append(max(results[i-1], nums[i] + results[i-2]))
            return results.pop()

附录:网上的code

.py
1
2

202. Happy Number (20min)

问题

  • 这道题在思路上很简单,如果用dict记录下每次的数字的话很轻松就能写出来了。但是如果想达到in-place的话则需要仿照之前写过的detect linked list cycle的方法。

感悟

附录:最终的code

isHappy.pyisHappy.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution(object):
    def isHappy(self, n):
        """
        :type n: int
        :rtype: bool
        """
        numList = [] # number list
        while n not in numList: # if is not visited
            numList.append(n) # append the current number
            sum = 0
            for i in str(n): # calculate the sum of squared of each digit
                sum += int(i)**2
            n = sum
        if numList.pop() == 1: # if the last one is 1, return True
            return True
        else:
            return False

附录:网上的code

.py
1
2