Python LeetCode(三)

算法不扎实:

1. Minimum Absolute Difference in BST

我一开始的想法是递归的计算和当前结点的左右子结点的值的difference,发现是没有理解题意,题目中说的是任意的两个结点的差的绝对值,而不是相连的结点。特别坑的是,因为是BST,那么就会存在根结点的左子树的最右子结点和根的情况,或者根结点的右结点的最左子结点和根的情况,显然我的做法无法满足情况。

这是我一开始的做法:

class Solution(object):
    val = 100000000
    def conclusive(self, root):
        if root == None:
            return
        if root.left:
            self.val = min(abs(root.val - root.left.val), self.val)
        if root.right:
            self.val = min(abs(root.val - root.right.val), self.val)
        self.conclusive(root.left)
        self.conclusive(root.right)
    def getMinimumDifference(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        self.conclusive(root)
        return self.val

因为BST很重要的一个特性,就是中序遍历会实现从小到大进行排序,也就是说它们的最小值必然发生在当前结点和它的左子树的最大值和右子树的最小值当中。既然是BST,那么我们就可以用中序遍历的特点来纪录上一个结点,就可以解决上面那个问题。

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

所以其递归的可以为先计算左子结点的结果,再将根结点加入进来,最后计算右子结点的结果。当然也可以转化成数组以后再比较也是一样的。在转化成数组以后,计算两两的差也是学习的点,可以用zip的特性,或者map(其实算是zip),或者用推导式。

class Solution(object):
    prev = None
    val = 100000000
    # 1nd: 纪录前面一个结点,并计算其差
    def conclusive(self, root):
        if root == None:
            return
        self.conclusive(root.left)
        if self.prev is not None:
            self.val = min(abs(root.val - self.prev.val), self.val)
        self.prev = root
        self.conclusive(root.right)
    def getMinimumDifference(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        self.conclusive(root)
        return self.val
    # 2nd: 既然是BST,则按照中序输出成数组再求差
    def getMinimumDifference2(self, root):
        if not root:
            return 0
        arr = []
        def inorder(root):
            if root:
                inorder(root.left)
                arr.append(root.val)
                inorder(root.right)
        inorder(root)
        return min([arr[i] - arr[i-1] for i in range[1:len(arr)]])
        # or return min([abs(a-b) for a, b in zip(arr, arr[1:])])
        # or return min(map(operator.sub, arr[1:], arr[:-1]))  # 这里的map可以并行操作

2. Move Zeroes

题目很简单,移动0,但是这里有个需要注意的地方,就是在删除0的时候,不能正序来删除,因为删除以后,下一个迭代器的地址变成了之前的下下个迭代器地址,这是因为你删除了以后,之后的就填补上来,它就以为填补上来的那个结点是当前结点,所以把下一个的地址设置成了填补上来的下个地址。所以我们要倒序来删除,因为是倒序,所以是前面的数组来填补,并不影响迭代器的地址。

当然了,也可以通过纪录0的位置,拿不是0的值进行交换,注意把它们的起始位置都设置成0。

   class Solution(object):
    def moveZeroes(self, nums):
        """
        :type nums: List[int]
        :rtype: void Do not return anything, modify nums in-place instead.
        """
        zero_num = nums.count(0)
        for i in range(len(nums)-1, -1, -1):
            if nums[i] == 0:
                nums.pop(i)
        nums.extend([0] * zero_num)
    # 不为0的值和上一个为0的值交换
    def moveZeroes2(self, nums):
        if nums.count(0) > 0:
            last_zero = 0
            for i in range(0, len(nums)):
                if nums[i] != 0:
                    nums[i], nums[last_zero] = nums[last_zero], nums[i]
                    last_zero += 1

做法多多

1. Find the Difference

这道题,主要学习的是找出双方那个不同的值。

class Solution(object):
    # 1nd: 使用list的remove
    def findTheDifference(self, s, t):
        """
        :type s: str
        :type t: str
        :rtype: str
        """
        temp=list(t)
        ss = list(s)
        for x in ss:
            temp.remove(x)
        return temp[0]
    # 2nd: 使用字符串的replace,类似于list中的remove
    def findTheDifference2(self, s, t):
        ss = ''
        while len(t) - len(s) == 1 and len(s):
            ss = s[0]
            s = s.replace(ss, '')
            t = t.replace(ss, '')
        # 如果此时相等,则说明之前删除的就是正确的,多删了一个而导致的长度相等
        if len(s) == len(t):
            return ss
        else:
            return t
    # 3nd: 使用异或操作,同样能够找出那个特别的字母
    # 因为遍历两次,而多出来的那个则只有一次,所以对全部值进行异或操作则可以得到单独的那个值
    def findTheDifference3(self, s, t):
        re = 0
        for i in s:
            re ^= ord(i)  # 转化成unicode码代表的数字
        for i in t:
            re ^= ord(i)
        return chr(re)
    # 4nd: 利用哈希的原理统计个数
    def findTheDifference4(self, s, t):
        d = [0] * 26
        base = ord('a')
        for i in s:
            d[ord(i)-base] += 1
        for i in t:
            d[ord(i)-base] -= 1
        for i, num in enumerate(d):
            if num != 0:
                return chr(base + i)
    # 5nd: 使用reduce来实现3中的操作,注意reduce是累加,其中函数必须传递两个参数,自然是前面计算出来的值和序列中新的值
    # 而且reduce是在functools模块里面,而map则是内建函数
    def findTheDifference5(self, s, t):
        return chr(functools.reduce(operator.xor, map(ord, s+t)))
    # 6nd:  使用Counter,Counter中的减去只会保留个数为正数的值
    def findTheDifference6(self, s, t):
        return list(Counter(t) - Counter(s))[0]
    # 7nd: 使用sorted + zip,先用sorted保证了顺序,再用zip找出不是相互对应的值
    def findTheDifference7(self, s, t):
        s, t = sorted(s), sorted(t) 
        if s[:-1] == t[:-1]:  # 过滤开头和结尾的情况
            return t[-1]
        elif s[1:] == t[1:]:
            return t[0]
        else:
            return [x[1] for x in zip(s, t) if x[0] != x[1]][0]

2. Invert Binary Tree

反转BST,一直以来,都不知道怎么写递归,你可以新建一个函数专门拿来递归,也可以在自身函数上递归。

   class Solution(object):
    def conclusive(self, root):
        if root == None:
            return None
        left = self.conclusive(root.left)
        right = self.conclusive(root.right)
        root.left, root.right = right, left
        return root
    # 1nd: 使用一个新的函数递归
    def invertTree(self, root):
        """
        :type root: TreeNode
        :rtype: TreeNode
        """
        if root == None:
            return None
        elif root.left == None and root.right == None:
            return root
        root = self.conclusive(root)
        return root
    # 2nd: 用自身函数递归
    def invertTree2(self, root):
        """
        :type root: TreeNode
        :rtype: TreeNode
        """
        if root is None:
            return
        root.left, root.right = root.right, root.left
        self.invertTree(root.left)
        self.invertTree(root.right)
        return root

3. Minimum Index Sum of Two Lists

我用的遍历,显然效率会比较差,特别是像这种找当前方是否在另一个地方出现,用字典的效率比较高,毕竟是O(1)。

   class Solution(object):
   # 1nd: 正常做法
    def findRestaurant(self, list1, list2):
        """
        :type list1: List[str]
        :type list2: List[str]
        :rtype: List[str]
        """
        res = []
        m = len(list1) + len(list2)
        for i, str in enumerate(list1):
            if list2.count(str) > 0:
                j = list2.index(str)
                if m >= i + j:
                    m = i + j
                    res.append(str)
        return res
    # 2nd: 使用字典
    def findRestaurant2(self, list1, list2):
        # 计算字典
        role1 = {x : i for i, x in enumerate(list1)}
        role2 = {x : i for i, x in enumerate(list2)}
        def minIndexNum(x):
            return role1.get(x, float('inf')) + role2.get(x, float('inf'))
        minindex = min(map(minIndexNum, role1))
        # 过滤出和为的值
        return filter(lambda x:minIndexNum(x) == minindex, list1)
    # 3nd: 使用set
    def findRestaurant3(self, list1, list2):
        common = set(list1) & set(list2)
        index_num = min(list1.index(x) + list2.index(x) for x in common)
        return [x for x in common if list1.index(x) + list2.index(x) == index_num]
posted @ 2017-08-05 15:44  banananana  阅读(188)  评论(0)    收藏  举报