Python每日一练(20230401) 最大子序和、前序中序构造二叉树、岛屿数量

简介: Python每日一练(20230401) 最大子序和、前序中序构造二叉树、岛屿数量

1. 最大子序和

给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

示例 1:

输入:nums = [-2,1,-3,4,-1,2,1,-5,4]

输出:6

解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。

示例 2:

输入:nums = [1]

输出:1

示例 3:

输入:nums = [0]

输出:0

示例 4:

输入:nums = [-1]

输出:-1

示例 5:

输入:nums = [-100000]

输出:-100000


提示:

  • 1 <= nums.length <= 3 * 10^4
  • -10^5 <= nums[i] <= 10^5

进阶:如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的 分治法 求解。

出处:

https://edu.csdn.net/practice/24394323

代码:

class Solution(object):
    def maxSubArray(self, nums):
        maxEndingHere = maxSofFar = nums[0]
        for i in range(1, len(nums)):
            maxEndingHere = max(maxEndingHere + nums[i], nums[i])
            maxSofFar = max(maxEndingHere, maxSofFar)
        return maxSofFar
# %%
s = Solution()
print(s.maxSubArray(nums = [-2,1,-3,4,-1,2,1,-5,4]))

输出:

6

分治法:

思路是将数组分成两部分,分别计算左半部分最大连续子序列和、右半部分最大连续子序列和以及跨越中间元素的最大连续子序列和,然后取三者的最大值即可。递归终止条件是分到只剩下一个元素的时候,此时最大连续子序列和就是该元素的值。

def maxSubArray(nums):
    if len(nums) == 1: return nums[0]
    mid = len(nums)//2
    left_sum = maxSubArray(nums[:mid])
    right_sum = maxSubArray(nums[mid:])
    cross_sum = crossSubArray(nums, mid)
    return max(left_sum, right_sum, cross_sum)
def crossSubArray(nums, mid):
    Infinity = float('-inf')
    left_sum, left_max = 0, Infinity
    for i in range(mid-1, -1, -1):
        left_sum += nums[i]
        left_max = max(left_max, left_sum)
        right_sum, right_max = 0, Infinity
        for i in range(mid, len(nums)):
            right_sum += nums[i]
            right_max = max(right_max, right_sum)
    return left_max + right_max
nums = [-2,1,-3,4,-1,2,1,-5,4]
print(maxSubArray(nums))

2. 从前序与中序遍历序列构造二叉树

给定一棵树的前序遍历 preorder 与中序遍历  inorder。请构造二叉树并返回其根节点。

示例 1:

Input: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]

Output: [3,9,20,null,null,15,7]


示例 2:

Input: preorder = [-1], inorder = [-1]

Output: [-1]


提示:

  • 1 <= preorder.length <= 3000
  • inorder.length == preorder.length
  • -3000 <= preorder[i], inorder[i] <= 3000
  • preorderinorder 均无重复元素
  • inorder 均出现在 preorder
  • preorder 保证为二叉树的前序遍历序列
  • inorder 保证为二叉树的中序遍历序列

出处:

https://edu.csdn.net/practice/24394324

代码1: 递归法

class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None
class Solution:
    def buildTree(self, preorder, inorder):
        if not preorder:
            return None
        root = TreeNode(preorder[0])
        i = inorder.index(root.val)
        root.left = self.buildTree(preorder[1 : i + 1], inorder[:i])
        root.right = self.buildTree(preorder[i + 1 :], inorder[i + 1 :])
        return root
def levelOrder(root):
    if not root: return []
    res, que = [], [root]
    while que:
        cur = que.pop(0)
        if cur:
            res.append(cur.val) 
            que.append(cur.left)
            que.append(cur.right)
        else:
            res.append(None)
    while res[-1] is None:
        res.pop()
    return res
s = Solution()
preorder = [3,9,20,15,7]
inorder = [9,3,15,20,7]
root = s.buildTree(preorder, inorder)
print(levelOrder(root))

输出:

[3, 9, 20, None, None, 15, 7]

代码2: 迭代法

class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None
    def levelOrder(self):
        if not self: return []
        res, que = [], [self]
        while que:
            cur = que.pop(0)
            if cur:
                res.append(cur.val) 
                que.append(cur.left)
                que.append(cur.right)
            else:
                res.append(None)
        while res[-1] is None:
            res.pop()
        return res
class Solution:
    def buildTree(self, preorder, inorder):
        if not preorder:
            return None
        root = TreeNode(preorder[0])
        cur, stack = 0, [root]
        for i in range(1, len(preorder)):
            node = TreeNode(preorder[i])
            if stack[-1].val != inorder[cur]:
                stack[-1].left = node
            else:
                while stack and stack[-1].val == inorder[cur]:
                    parent = stack.pop()
                    cur += 1
                parent.right = node
            stack.append(node)
        return root
s = Solution()
preorder = [3,9,20,15,7]
inorder = [9,3,15,20,7]
root = s.buildTree(preorder, inorder)
print(root.levelOrder())

3. 岛屿数量

给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。

岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。

此外,你可以假设该网格的四条边均被水包围。

示例 1:

输入:grid = [

["1","1","1","1","0"],

["1","1","0","1","0"],

["1","1","0","0","0"],

["0","0","0","0","0"]

]

输出:1


示例 2:

输入:grid = [

["1","1","0","0","0"],

["1","1","0","0","0"],

["0","0","1","0","0"],

["0","0","0","1","1"]

]

输出:3


提示:

  • m == grid.length
  • n == grid[i].length
  • 1 <= m, n <= 300
  • grid[i][j] 的值为 '0''1'

出处:

https://edu.csdn.net/practice/24394325

代码1: DFS

遍历所有相邻的陆地,并将它们标记为已访问,直到遍历完整个岛屿。统计访问的岛屿数量,最终输出。

from typing import List
class Solution:
    def depthSearch(self, grid, i, j):
        if i < 0 or j < 0 or i >= len(grid) or j >= len(grid[0]):
            return
        if grid[i][j] == "0":
            return
        grid[i][j] = "0"
        self.depthSearch(grid, i - 1, j)
        self.depthSearch(grid, i + 1, j)
        self.depthSearch(grid, i, j - 1)
        self.depthSearch(grid, i, j + 1)
    def numIslands(self, grid: List[List[str]]) -> int:
        if not grid:
            return 0
        w, h = len(grid[0]), len(grid)
        cnt = 0
        for i in range(h):
            for j in range(w):
                if grid[i][j] == "1":
                    self.depthSearch(grid, i, j)
                    cnt += 1
        return cnt
# %%
s = Solution()
grid = [
["1","1","1","1","0"],
["1","1","0","1","0"],
["1","1","0","0","0"],
["0","0","0","0","0"]]
print(s.numIslands(grid))
grid = [
["1","1","0","0","0"],
["1","1","0","0","0"],
["0","0","1","0","0"],
["0","0","0","1","1"]]
print(s.numIslands(grid))

输出:

1

3

闭包函数形式:

def numIslands(grid):
    if not grid: return 0
    row, col = len(grid), len(grid[0])
    count = 0
    def dfs(i, j):
        if not (0<=i<row and 0<=j<col and grid[i][j] == '1'):
            return
        grid[i][j] = '0'
        dfs(i-1, j)
        dfs(i+1, j)
        dfs(i, j-1)
        dfs(i, j+1)
    for i in range(row):
        for j in range(col):
            if grid[i][j] == '1':
                dfs(i, j)
                count += 1
    return count

代码2: BFS

用队列遍历所有相邻的陆地,并将它们标记为已访问,直到遍历完整个岛屿。

from collections import deque
def numIslands(grid):
    if not grid: return 0
    row, col = len(grid), len(grid[0])
    count = 0
    queue = deque()
    direct = [(0,1), (0,-1), (1,0), (-1,0)]
    for i in range(row):
        for j in range(col):
            if grid[i][j] == '1':
                count += 1
                queue.append((i, j))
                grid[i][j] = '0'
                while queue:
                    p, q = queue.popleft()
                    for d in direct:
                        x, y = p + d[0], q + d[1]
                        if 0<=x<row and 0<=y<col and grid[x][y] == '1':
                            queue.append((x, y))
                            grid[x][y] = '0'
    return count
grid = [
["1","1","1","1","0"],
["1","1","0","1","0"],
["1","1","0","0","0"],
["0","0","0","0","0"]]
print(numIslands(grid))
grid = [
["1","1","0","0","0"],
["1","1","0","0","0"],
["0","0","1","0","0"],
["0","0","0","1","1"]]
print(numIslands(grid))

代码3: 并查集

将所有陆地的坐标看作节点,相邻陆地之间就是边。利用并查集将所有相邻的陆地节点进行合并,最终统计联通块的数量就是岛屿的数量。

class UnionFind:
    def __init__(self, grid):
        m, n = len(grid), len(grid[0])
        self.count = 0
        self.parent = [-1] * (m * n)
        for i in range(m):
            for j in range(n):
                if grid[i][j] == '1':
                    self.parent[i * n + j] = i * n + j
                    self.count += 1
    def find(self, x):
        if self.parent[x] == x:
            return x
        self.parent[x] = self.find(self.parent[x])
        return self.parent[x]
    def union(self, x, y):
        rootx = self.find(x)
        rooty = self.find(y)
        if rootx != rooty:
            self.parent[rooty] = rootx
            self.count -= 1
def numIslands(grid):
    if not grid:
        return 0
    uf = UnionFind(grid)
    m, n = len(grid), len(grid[0])
    direct = [(0,1), (0,-1), (1,0), (-1,0)]
    for i in range(m):
        for j in range(n):
            if grid[i][j] == '1':
                for d in direct:
                    x, y = i + d[0], j + d[1]
                    if 0<=x<m and 0<=y<n and grid[x][y] == '1':
                        uf.union(i * n + j, x * n + y)
    return uf.count
grid = [
["1","1","1","1","0"],
["1","1","0","1","0"],
["1","1","0","0","0"],
["0","0","0","0","0"]]
print(numIslands(grid))
grid = [
["1","1","0","0","0"],
["1","1","0","0","0"],
["0","0","1","0","0"],
["0","0","0","1","1"]]
print(numIslands(grid))

🌟 每日一练刷题专栏 🌟

持续,努力奋斗做强刷题搬运工!

👍 点赞,你的认可是我坚持的动力!

🌟 收藏,你的青睐是我努力的方向!

评论,你的意见是我进步的财富!  

主页:https://hannyang.blog.csdn.net/


目录
相关文章
|
14天前
|
存储 算法 Python
文件管理系统中基于 Python 语言的二叉树查找算法探秘
在数字化时代,文件管理系统至关重要。本文探讨了二叉树查找算法在文件管理中的应用,并通过Python代码展示了其实现过程。二叉树是一种非线性数据结构,每个节点最多有两个子节点。通过文件名的字典序构建和查找二叉树,能高效地管理和检索文件。相较于顺序查找,二叉树查找每次比较可排除一半子树,极大提升了查找效率,尤其适用于海量文件管理。Python代码示例包括定义节点类、插入和查找函数,展示了如何快速定位目标文件。二叉树查找算法为文件管理系统的优化提供了有效途径。
46 5
|
5月前
|
Python
【Leetcode刷题Python】剑指 Offer 32 - III. 从上到下打印二叉树 III
本文介绍了两种Python实现方法,用于按照之字形顺序打印二叉树的层次遍历结果,实现了在奇数层正序、偶数层反序打印节点的功能。
65 6
|
5月前
|
Python
【Leetcode刷题Python】114. 二叉树展开为链表
LeetCode上114号问题"二叉树展开为链表"的Python实现,通过先序遍历二叉树并调整节点的左右指针,将二叉树转换为先序遍历顺序的单链表。
32 3
【Leetcode刷题Python】114. 二叉树展开为链表
|
5月前
|
索引 Python
【Leetcode刷题Python】从列表list中创建一颗二叉树
本文介绍了如何使用Python递归函数从列表中创建二叉树,其中每个节点的左右子节点索引分别是当前节点索引的2倍加1和2倍加2。
79 7
|
5月前
|
存储 算法 Python
【Leetcode刷题Python】297. 二叉树的序列化与反序列化
LeetCode第297题"二叉树的序列化与反序列化"的Python语言解决方案,包括序列化二叉树为字符串和反序列化字符串为二叉树的算法实现。
30 5
|
5月前
|
Python
【Leetcode刷题Python】剑指 Offer 32 - II. 从上到下打印二叉树 II
本文提供了一种Python实现方法,用于层次遍历二叉树并按层打印结果,每层节点按从左到右的顺序排列,每层打印到一行。
42 3
|
5月前
|
Python
【Leetcode刷题Python】剑指 Offer 32 - I. 从上到下打印二叉树
本文介绍了使用Python实现从上到下打印二叉树的解决方案,采用层次遍历的方法,利用队列进行节点的访问。
39 2
|
5月前
|
Python
【Leetcode刷题Python】257. 二叉树的所有路径
LeetCode第257题"二叉树的所有路径"的Python语言解决方案,通过深度优先搜索算法来找到并返回所有从根节点到叶子节点的路径。
44 2
|
5月前
|
Python
【Leetcode刷题Python】111. 二叉树的最小深度
LeetCode第111题"二叉树的最小深度"的Python语言解决方案,通过递归计算从根节点到最近叶子节点的最短路径上的节点数量。
23 2
|
5月前
|
Python
【Leetcode刷题Python】104. 二叉树的最大深度
LeetCode第104题"二叉树的最大深度"的Python语言解决方案,使用递归方法来计算给定二叉树的最大深度。
33 2