• leetcode刷题 420~


    题目421题

    数组中两个数的最大异或值

    给定一个非空数组,数组中元素为 a0, a1, a2, … , an-1,其中 0 ≤ ai < 231 。

    找到 ai 和aj 最大的异或 (XOR) 运算结果,其中0 ≤ i,  j < n 。

    你能在O(n)的时间解决这个问题吗?

    示例:

    输入: [3, 10, 5, 25, 2, 8]

    输出: 28

    解释: 最大的结果是 5 ^ 25 = 28.

    思路

    字典树:将数组中元素转化为二进制后,放入字典树中,同时计算该数字在字典树中所能得到的最大异或值。

    实现

    class Solution:
        def findMaximumXOR(self, nums: List[int]) -> int:
            trie = {}
            L = len(bin(max(nums))) - 2
            nums = [[(x >> i) & 1 for i in range(L)][::-1] for x in nums]
            result = 0
            for num in nums:
                node = trie
                revnode = trie
                cur = 0
                for bit in num:
                    if not bit in node:
                        node[bit] = {}
                    node = node[bit]
                    revbit = 1 - bit
                    if revbit in revnode:
                        cur = (cur<<1) | 1
                        revnode = revnode[revbit]
                    else:
                        cur = cur << 1
                        revnode = revnode[bit]
                result = max(result, cur)
            return result

    题目427题

    建立四叉树

    思路

    递归

    实现

    class Solution:
        def construct(self, grid: List[List[int]]) -> 'Node':
            n = len(grid)
    
            def helper(r, c, l) -> 'Node':
                sign = grid[r][c]
                flag = True
                for i in range(r,r+l):
                    for j in range(c,c+l):
                        if grid[i][j] != sign:
                            flag = False
                            break
                if flag:
                    return Node(sign, flag, None, None, None, None)
                else:
                    l = l//2
                    topLeft = helper(r,c,l)
                    topRight = helper(r,c+l,l)
                    bottomLeft = helper(r+l,c,l)
                    bottomRight = helper(r+l,c+l,l)
                    return Node(sign, flag,topLeft, topRight, bottomLeft, bottomRight)
            return helper(0,0,n)

    题目429题

    N叉树的层次遍历

    给定一个 N 叉树,返回其节点值的层序遍历。 (即从左到右,逐层遍历)。

    思路

    递归或者广度优先遍历

    实现

    class Solution:
        def levelOrder(self, root: 'Node') -> List[List[int]]:
            result = []
            if not root:
                return result
            def helper(level,node):
                if len(result) == level:
                    result.append([])
                result[level].append(node.val)
                for child in node.children:
                    helper(level+1, child)
            helper(0,root)
            return result

    题目430题

    扁平化多级双向链表

    多级双向链表中,除了指向下一个节点和前一个节点指针之外,它还有一个子链表指针,可能指向单独的双向链表。这些子列表也可能会有一个或多个自己的子项,依此类推,生成多级数据结构,如下面的示例所示。

    给你位于列表第一级的头节点,请你扁平化列表,使所有结点出现在单级双链表中。

    思路

    递归

    实现

    class Solution:
        def flatten(self, head: 'Node') -> 'Node':
            result = head
            while head:
                if head.child:
                    next_node = head.next
                    child_node = self.flatten(head.child)
                    head.child = None
                    head.next = child_node
                    child_node.prev = head
                    while child_node.next:
                        child_node = child_node.next
                    if next_node:
                        next_node.prev = child_node
                    child_node.next = next_node
                    head = next_node
                else:
                    head = head.next
            return result

    题目433题

    最小基因变化

    一条基因序列由一个带有8个字符的字符串表示,其中每个字符都属于 "A", "C", "G", "T"中的任意一个。

    假设我们要调查一个基因序列的变化。一次基因变化意味着这个基因序列中的一个字符发生了变化。

    例如,基因序列由"AACCGGTT" 变化至 "AACCGGTA" 即发生了一次基因变化。

    与此同时,每一次基因变化的结果,都需要是一个合法的基因串,即该结果属于一个基因库。

    现在给定3个参数 — start, end, bank,分别代表起始基因序列,目标基因序列及基因库,请找出能够使起始基因序列变化为目标基因序列所需的最少变化次数。如果无法实现目标变化,请返回 -1。

    思路

    广度优先遍历

    实现

    class Solution:
        def minMutation(self, start: str, end: str, bank: List[str]) -> int:
            if end not in bank:
                return -1
            gene = "ACGT"
            bank = set(bank)
            q = collections.deque()
            q.append((start,0))
            while q:
                word, level = q.popleft()
                if word == end:
                    return level
                for i in range(8):
                    for j in gene:
                        temp = word[0:i] + j + word[i+1:]
                        if temp in bank:
                            q.append((temp,level+1))
                            bank.remove(temp)
            return -1

    题目434题

    字符串中的单词数

    统计字符串中的单词个数,这里的单词指的是连续的不是空格的字符。

    思路实现

    class Solution:
        def countSegments(self, s: str) -> int:
            result, flag = 0, True
            for i in s:
                if i != " " and flag:
                    result += 1
                    flag = False
                if i == " ":
                    flag = True
            return result

    题目435题

    无重叠区间

    给定一个区间的集合,找到需要移除区间的最小数量,使剩余区间互不重叠。

    注意:

    可以认为区间的终点总是大于它的起点。
    区间 [1,2] 和 [2,3] 的边界相互“接触”,但没有相互重叠。

    思路

    贪心算法:

    当按照起点先后顺序考虑区间的时候:

    情况一

    当前考虑的两个区间不重叠:

    在这种情况下,不移除任何区间,将 prev 赋值为后面的区间,移除区间数量不变。

    情况二

    两个区间重叠,后一个区间的终点在前一个区间的终点之前。

    这种情况下,我们可以简单地只用后一个区间。这是显然的,因为后一个区间的长度更小,可以留下更多的空间(A 和 B),容纳更多的区间。因此, prev更新为当前区间,移除区间的数量 + 1。

    情况三

    两个区间重叠,后一个区间的终点在前一个区间的终点之后。

    这种情况下,我们用贪心策略处理问题,直接移除后一个区间。为了理解这种做法的正确性,请看下图,该图包含了所有可能的情况。从图可以清楚地看出,选择前移区间总会得到更好的结果。因此,prev不变,移除区间的数量 + 1。

    实现

    class Solution:
        def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int:
            if not intervals:
                return 0
            intervals = sorted(intervals,key= (lambda x:[x[0],x[1]]))
            prel, prer = intervals[0][0], intervals[0][1]
            result = 0
            for index in range(1,len(intervals)):
                left = intervals[index][0]
                right = intervals[index][1]
                if prer > left:
                    if prer > right:
                        prel, prer = left, right
                    result += 1
                else:
                    prel, prer = left, right
            return result
                

    题目436题

    寻找右区间

    给定一组区间,对于每一个区间 i,检查是否存在一个区间 j,它的起始点大于或等于区间 i 的终点,这可以称为 j 在 i 的“右侧”。

    对于任何区间,你需要存储的满足条件的区间 j 的最小索引,这意味着区间 j 有最小的起始点可以使其成为“右侧”区间。如果区间 j 不存在,则将区间 i 存储为 -1。最后,你需要输出一个值为存储的区间值的数组。

    注意:

    你可以假设区间的终点总是大于它的起始点。
    你可以假定这些区间都不具有相同的起始点。

    思路

    二分法:记录每个区间的左值,将其排序。每个值的右值在其寻找最大小于区间左值的点。

    实现

    class Solution:
        def findRightInterval(self, intervals: List[List[int]]) -> List[int]:
            result = [-1 for i in range(len(intervals))]
            left = dict()
            for i in range(len(intervals)):
                left[intervals[i][0]] = i
            test = sorted(left.keys())
            for i in range(len(intervals)):
                l, r = 0 , len(test)-1
                while l < r:
                    mid = l + (r-l)//2
                    if test[mid] >= intervals[i][1]:
                        r = mid
                    else:
                        l = mid+1
                if test[l] >= intervals[i][1]:
                    result[i] = left[test[l]]
            return result

    题目437题

    路径总和III

    给定一个二叉树,它的每个结点都存放着一个整数值。

    找出路径和等于给定数值的路径总数。

    路径不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。

    二叉树不超过1000个节点,且节点数值范围是 [-1000000,1000000] 的整数。

    思路

    深度优先遍历

    实现

    class Solution:
        def pathSum(self, root: TreeNode, sum: int) -> int:
            result = 0
            def dfs(node,tmepsum):
                if not node:
                    return
                nextsum = [0]
                for i in tmepsum:
                    temp = i + node.val
                    if temp == sum:
                        nonlocal result
                        result += 1
                    nextsum.append(temp)
                dfs(node.left,nextsum)
                dfs(node.right,nextsum)
            dfs(root,[0])
            return result

    题目438题

    找到字符串中所有字母异位词

    给定一个字符串 s 和一个非空字符串 p,找到 s 中所有是 p 的字母异位词的子串,返回这些子串的起始索引。

    字符串只包含小写英文字母,并且字符串 s 和 p 的长度都不超过 20100。

    说明:

    字母异位词指字母相同,但排列不同的字符串。
    不考虑答案输出的顺序。

    思路

    滑动窗口

    实现

    class Solution:
        def findAnagrams(self, s: str, p: str) -> List[int]:
            ls, lp = len(s), len(p)   
            result = []
            if ls < lp:
                return result
            dict_s, dict_p = dict.fromkeys(string.ascii_lowercase, 0), dict.fromkeys(string.ascii_lowercase, 0)
            for index in range(lp):
                words, wordp = s[index], p[index]
                dict_p[wordp] += 1
                dict_s[words] += 1
            for index in range(ls-lp+1):
                if dict_p == dict_s:
                    result.append(index)
                if index == ls - lp:
                    break
                old, new = s[index], s[index+lp]
                dict_s[old] -= 1
                dict_s[new] += 1
            return result

     

  • 相关阅读:
    cygwin补充安装gcc/g++的方法
    JS中获取request的值,非常好用的JS代码
    登录页面跳出框架的JS
    asp.net DataTable转JSON
    ASP.NET文件下载的实用方法
    史上最牛X到的身份证号码验证,测试误差为0
    nopcommerce插件深度剖析
    C# foreach,linq,delegate集合查询的性能比较
    jquery tab插件精简版
    建议博客园成立中国的开源项目组织,同意的顶起
  • 原文地址:https://www.cnblogs.com/mgdzy/p/13987027.html
Copyright © 2020-2023  润新知