Python LeetCode(二)

Python不熟悉

1. Reverse Words in a String III

这道题目我做出来了,但是我使用C语言的思想去做的,但是Python提供了reverse和map函数都可以实现;

我的实现:

def reverseWords(s):
    """
    :type s: str
    :rtype: str
    """
    arr = ''.join(list(reversed(s))).split(' ')
    res = ""
    while len(arr) != 0:
        res += arr.pop() + ' '
    return res.strip(' ')

上面的代码可以简化为

def reverseWords2(s):
    return ' '.join([''.join(reversed(list(i))) for i in s.split(' ')])

使用map可以更简单:

def reverseWords3(s):
    return " ".join(map(lambda x:x[::-1], s.split()))

除此之外,我才知道join方法是用来连接itrerable里面的每个字符串的,我一开始还以为是只在前面拿来连接的,还有map函数可以用在对可迭代元素里面的每一个元素都进行操作的时候。

2. Reshape the Matrix

# 1nd 简易版本
def matrixReshape(nums, r, c):
    """
    :type nums: List[List[int]]
    :type r: int
    :type c: int
    :rtype: List[List[int]]
    """
    l = len(nums) * len(nums[0])
    if l != r * c:
        return nums
    temp = [j for i in nums for j in i]
    i = 0
    arr = []
    while i < r:
        arr.append(temp[i * c:i * c+c])
        i += 1
    return arr
# 2nd 使用zip
def matrixReshape2(nums, r, c):
    flat = sum(nums, [])
    if len(flat) != r * c:
        return nums
    tuples = zip(*([iter(flat)] * c))
    return map(list, tuples)
# 3nd 使用itertools
import itertools
def matrixReshape3(nums, r, c):
    if r * c != len(nums) * len(nums[0]):
        return nums
    it = itertools.chain(*nums)
    return [list(itertools.islice(it, c)) for _ in range(r)]
# 4nd 使用numpy
import numpy as np
def matrixReshape4(nums, r, c):
    try:
        return np.reshape(nums, (r, c)).tolist()
    except:
        return nums

这里面有个zip(*[iter(...)*n])可以实现对序列的切割,变成n个数据一个tuple。

3. Fizz Buzz

这道题很简单,但是有些人写的非常Pythonnic,让我真的是第一次知道还能这么写。

class Solution(object):
    def getitem(self, i):
        if i % 3 == 0 and i % 5 == 0:
            return 'FizzBuzz'
        elif i % 3 == 0:
            return 'Fizz'
        elif i % 5 == 0:
            return 'Buzz'
        else:
            return str(i)
    # 1nd: 我的方法,使用map
    def fizzBuzz(self, n):
        """
        :type n: int
        :rtype: List[str]
        """
        return map(self.getitem, [i for i in range(1, n + 1)])
    # 2nd: 字符串相乘
    def fizzBuzz2(self, n):
        return ['Fizz' * (not i % 3) + 'Buzz' * (not i % 5) or str(i) for i in range(1, n + 1)]
    # 3nd: FizzBuzz后面那个是字符串的index
    def fizzBuzz3(self, n):
        return ['FizzBuzz'[i % -3 & -4:i % -5 & 8 ^ 12] or repr(i) for i in range(1, n + 1)]
    # 4nd: 后面那个是前面那个list的index
    def fizzBuzz4(self, n):
        return [[str(d), "Fizz", "Buzz", "FizzBuzz"][(not d % 3) + (not d % 5) * 2] for d in range(1, n + 1)]
    # 5nd: 正常写法
    def fizzBuzz5(self, n):
        return [('Fizz' if i % 3 == 0 else '') + ('Buzz' if i % 5 == 0 else '')
                + (str(i) if not (i % 3 == 0 or i % 5 == 0) else '') for i in range(1, n + 1)]

4. Keyboard Row

这道题有一些技巧,像是使用set对象的issubset方法或者是使用正则匹配等等

class Solution(object):
    str1 = 'qwertyuiop'
    str2 = 'asdfghjkl'
    str3 = 'zxcvbnm'
    # 1nd 逐个查找
    def isstr1(self, w):
        return self.str1.find(w) != -1
    def isstr2(self, w):
        return self.str2.find(w) != -1
    def isstr3(self, w):
        return self.str3.find(w) != -1
    def isstr(self, w):
        if self.isstr1(w):
            return self.str1
        elif self.isstr2(w):
            return self.str2
        else:
            return self.str3
    def findWords(self, words):
        """
        :type words: List[str]
        :rtype: List[str]
        """
        arr = []
        for word in words:
            temp = word.lower()
            str = self.isstr(temp[0])
            isvalid = True
            for w in temp:
                if str.find(w) == -1:
                    isvalid = False
                    break
            if isvalid == True:
                arr.append(word)
        return arr
    # 2nd 正则匹配 + filter
    def findWords2(self, words):
        return filter(re.compile('(?i)([qwertyuiop]*|[asdfghjkl]*|[zxcvbnm]*)$').match, words)
    # 3nd 使用issubset
    def findWords3(self, words):
        line1, line2, line3 = set('qwertyuiop'), set('asdfghjkl'), set('zxcvbnm')
        return filter(lambda x:set(x.lower()).issubset(line1) or set(x.lower()).issubset(line2) or set(x.lower()).issubset(line3), words)

算法不扎实:

1. Construct String from Binary Tree

这道递归题我并不会做,准确的是不知道递归的规律在哪里?其实根据答案的规律则可以得到

根结点(左子结点)(右子结点)

所以其递归的可以为先计算左子结点的结果,再计算右子结点的结果,最后将根结点加入进来。

class Solution(object):
    # 我写的方法,错误,直接返回子结点计算的结果
    def concursive(self, root, res):
        if not root :
            return ''
        res += str(root.val)
        if root.left:
            return self.concursive(root.left, '(' + res + ')')
        if root.right:
            return self.concursive(root.right, '(' + res + ')')
        return res
    # 错误示范
    def tree2str(self, t):
        """
        :type t: TreeNode
        :rtype: str
        """
        res = ''
        return self.concursive(t, res)
    # 1nd: 正确的递归
    def tree2str2(self, t):
        """
        :type t: TreeNode
        :rtype: str
        """
        if not t:
            return ""
        res = ""
        left = self.tree2str2(t.left)
        right = self.tree2str2(t.right)
        # 处理左结点可能为空的情况
        if left or right:
            res += "(%s)" % left
        if right:
            res += "(%s)" % right
        return str(t.val) + res
    # 2nd: 上面代码的简化版本
    def tree2str3(self, t):
        if not t: return ''
        left = '({})'.format(self.tree2str3(t.left)) if (t.left or t.right) else ''
        right = '({})'.format(self.tree2str3(t.right)) if t.right else ''
        return '{}{}{}'.format(t.val, left, right)
    # 3nd: 判断各种情况,可以减少运行时间
    def tree2str4(self, t):
        """
        :type t: TreeNode
        :rtype: str
        """
        if not t:
            return ""
        if t.left is None and t.right is None:
            return str(t.val)
        elif t.left is None:
            return str(t.val) + '()(' + self.tree2str4(t.right) + ')'
        elif t.right is None:
            return str(t.val) + '(' + self.tree2str4(t.left) + ')'
        else:
            return str(t.val) + '(' + self.tree2str4(t.left) + ')' + '(' + self.tree2str4(t.right) + ')'

知识盲点

1. Next Greater Element I

这道题,主要学习的是如何在字典中存储数组里面的一个数字对应的下一个比它大的数字。

class Solution(object):
    def getitem(self, x):
        idx = self.nums.index(x)
        arr = filter(lambda i:i > x, self.nums[idx:])
        if len(arr) == 0:
            return -1
        else:
            return arr[0]
    # 1nd: map+index+filter
    def nextGreaterElement(self, findNums, nums):
        self.nums = nums
        return map(self.getitem, findNums)
# 2nd: 原理是通过字典存储nums中当前元素对应的下一个比当前元素大的值,查找的时候类似并查集
    def nextGreaterElement3(self, findNums, nums):
        """
        :type findNums: List[int]
        :type nums: List[int]
        :rtype: List[int]
        """
        if not nums:
            return []
        d = {nums[-1]: -1}  # 最后一个元素必然为-1,因为找不到后面的值了
        # 去掉最后一个的个数,到-1结束,说明到0,-1表示反转
        for i in range(len(nums) - 2, -1, -1): 
            if nums[i] < nums[i + 1]:  # 说明后面存在大的数
                d[nums[i]] = nums[i + 1]
            else:
                # 从当前位置的下一个位置开始找,因为d里面存储了比当前值更大的下一个值
                t = d[nums[i + 1]]
                while t != -1 and nums[i] > t:
                    t = d[t]
                d[nums[i]] = t
        return [d[i] for i in findNums]
    # 3nd: 和上面的原理是一样的,stack最后一个纪录就是上一个的值,dic则纪录着上一个的值对应的比它要大的下一个值
    def nextGreaterElement4(self, findNums, nums):
        """
        :type findNums: List[int]
        :type nums: List[int]
        :rtype: List[int]
        """
        dic, stack = {}, []
        for n in nums:
            while len(stack) and stack[-1] < n:
                dic[stack.pop()] = n
            stack.append(n)
        return [dic.get(n, -1) for n in findNums]

2. Single Number

如果数组其它均是两个元素,只有一个元素是一个,则通过对多个元素进行异或的操作,可以找出那个元素。

    # 对数组中的元素进行异或操作,对多个数进行异或操作以后则变成只有出现一次数的值
    def singleNumber2(self, nums):
        ans = nums[0]
        for x in nums[1:]:
            ans = ans ^ x
        return ans
posted @ 2017-08-05 15:41  banananana  阅读(313)  评论(0)    收藏  举报