• 第7周Leetcode记录


    10.30 32.移动石子

    三枚石子放置在数轴上,位置分别为 a,b,c。

    每一回合,我们假设这三枚石子当前分别位于位置 x, y, z 且 x < y < z。从位置 x 或者是位置 z 拿起一枚石子,并将该石子移动到某一整数位置 k 处,其中 x < k < z 且 k != y。

    当你无法进行任何移动时,即,这些石子的位置连续时,游戏结束。

    要使游戏结束,你可以执行的最小和最大移动次数分别是多少? 以长度为 2 的数组形式返回答案:answer = [minimum_moves, maximum_moves]

    思路

    最少0或1或2,分情况。

    我的解

    class Solution:
        def numMovesStones(self, a: int, b: int, c: int) -> List[int]:
            tmp = [a,b,c] # 先对xyz赋值
            tmp.sort()
            x,y,z = tmp[0],tmp[1],tmp[2]
            if x + 1 == y and y + 1 == z: # a,b,c连续
                return [0,0]
            else:
                if y-x == 2 or z-y == 2 or (x+1 == y or y + 1 == z):  # 中间隔一个或者有两个挨着
                    minimum_moves = 1
                else:
                    minimum_moves = 2
                maximum_moves = (y-x)+(z-y)-2
            return [minimum_moves,maximum_moves]
    

    11.1 33. 拼写单词

    给你一份『词汇表』(字符串数组) words 和一张『字母表』(字符串) chars。

    假如你可以用 chars 中的『字母』(字符)拼写出 words 中的某个『单词』(字符串),那么我们就认为你掌握了这个单词。

    注意:每次拼写(指拼写词汇表中的一个单词)时,chars 中的每个字母都只能用一次。

    返回词汇表 words 中你掌握的所有单词的 长度之和。

    输入:words = ["cat","bt","hat","tree"], chars = "atach"
    输出:6
    解释: 
    可以形成字符串 "cat" 和 "hat",所以答案是 3 + 3 = 6。
    

    思路

    用counter将chars每个字母出现的次数提取出来,分别遍历数组里每一个单词的counter,符合条件的即是。

    我的解

    class Solution:
        def countCharacters(self, words: List[str], chars: str) -> int:
            from collections import Counter
            from copy import deepcopy
            chars_dic = Counter(chars)
            res_list = []
    
            for word in words:
                fit = 1
                dic_copy = deepcopy(chars_dic)
                per_dic = Counter(word)
                dic_copy.subtract(per_dic)
                for i in dic_copy.values():
                    if i < 0:
                        fit = 0
                        break
                if fit:
                    res_list.append(word)
            return len(''.join(res_list))
    

    11.2 34. 搜索旋转排序数组

    给你一个升序排列的整数数组 nums ,和一个整数 target 。

    假设按照升序排序的数组在预先未知的某个点上进行了旋转。(例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。

    请你在数组中搜索 target ,如果数组中存在这个目标值,则返回它的索引,否则返回 -1 。

    输入:nums = [4,5,6,7,0,1,2], target = 0
    输出:4
    
    输入:nums = [4,5,6,7,0,1,2], target = 3
    输出:-1
    

    思路

    可以遍历,时间复杂度高。

    利用二分法,分为L,R两个数组,因为是有序数组分的。如果L和R都是有序,判断target在哪个区间。继续二分。如果L[0] > L[-1] 说明L无序,如果target在R里,可以丢弃L,如果target不在,继续二分。判断并丢弃。

    最优解

    class Solution:
        @classmethod
        def search(self, nums: list, target: int) -> int:
            if not nums:
                return -1
            l, r = 0, len(nums) - 1
            while l <= r:
                mid = (l + r) // 2
                if nums[mid] == target:
                    return mid
                if nums[0] <= nums[mid]:
                    if nums[0] <= target < nums[mid]:
                        r = mid - 1
                    else:
                        l = mid + 1
                else:
                    if nums[mid] < target <= nums[len(nums) - 1]:
                        l = mid + 1
                    else:
                        r = mid - 1
            return -1
    

    总结

    每次可以至少得到一个有序区间,如果target在此区间丢弃另一个,如果不在丢弃自身。

    11.3 35. 恢复二叉搜索树

    给你二叉搜索树的根节点 root ,该树中的两个节点被错误地交换。请在不改变其结构的情况下,恢复这棵树。

    img

    输入:root = [1,3,null,null,2]
    输出:[3,1,null,null,2]
    解释:3 不能是 1 左孩子,因为 3 > 1 。交换 1 和 3 使二叉搜索树有效。
    

    img

    输入:root = [3,1,4,null,null,2]
    输出:[2,1,4,null,null,3]
    解释:2 不能在 3 的右子树中,因为 2 < 3 。交换 2 和 3 使二叉搜索树有效。
    

    最优解一:显示中序遍历

    • 为什么用中序

      根据题意,任意根节点,左边比根节点小,右边比根节点大。有序的搜素树中序遍历一定有序

      class Solution(object):
          def recoverTree(self, root):
              nodes = []
              # 中序遍历二叉树,并将遍历的结果保存到list中        
              def dfs(root):
                  if not root:
                      return
                  dfs(root.left)
                  nodes.append(root)
                  dfs(root.right)
              dfs(root)
              x = None
              y = None
              pre = nodes[0]
              # 扫面遍历的结果,找出可能存在错误交换的节点x和y
              for i in xrange(1,len(nodes)):
                  if pre.val>nodes[i].val:
                      y=nodes[i]
                      if not x:
                          x = pre
                  pre = nodes[i]
              # 如果x和y不为空,则交换这两个节点值,恢复二叉搜索树 
              if x and y:
                  x.val,y.val = y.val,x.val
      
      
  • 相关阅读:
    UML类关系:依赖、关联、聚合、组合(收藏)
    java常用设计模式八:代理模式
    java常用设计模式三:原型模式
    java常用设计模式总览
    java常用设计模式七:装饰模式
    java常用设计模式六:适配器模式
    Sword C语言原子操作
    C语言 宽字符串
    C语言 字符串切割
    C语言 sscanf函数补充
  • 原文地址:https://www.cnblogs.com/jimmyhe/p/13940968.html
Copyright © 2020-2023  润新知