LeetCode 中等題解(3)

34 在排序數組中查找元素的第一個和最後一個位置

Question

給定一個按照升序排列的整數數組 nums,和一個目標值 target。找出給定目標值在數組中的開始位置和結束位置。

你的算法時間複雜度必須是 O(log n) 級別。

如果數組中不存在目標值,返回 [-1, -1]

示例 1:

輸入: nums = [5,7,7,8,8,10], target = 8
輸出: [3,4]

示例 2:

輸入: nums = [5,7,7,8,8,10], target = 6
輸出: [-1,-1]

Answer

#
# @lc app=leetcode.cn id=34 lang=python3
#
# [34] 在排序數組中查找元素的第一個和最後一個位置
#


# @lc code=start
class Solution:
    def searchRange(self, nums: List[int], target: int) -> List[int]:
        start = 0
        end = len(nums) - 1
        # 空數組的情況
        if end < 0:
            return [-1, -1]
        # 二分查找target落在的位置
        while (start < end):
            if nums[start] == target:
                end = start
                break
            if nums[end] == target:
                start = end
                break
            mid = (start + end) // 2
            if nums[mid] < target:
                start = mid + 1
            if nums[mid] > target:
                end = mid - 1
            if nums[mid] == target:
                start = mid
                end = mid
                break
        # 如果找不到target
        if nums[start] != target:
            return [-1, -1]
        # 找到target,向前向後搜索邊界
        while (start > 0 and nums[start - 1] == target):
            start -= 1
        while (end < len(nums) - 1 and nums[end + 1] == target):
            end += 1

        return [start, end]


# @lc code=end

36 有效的數獨

Question

判斷一個 9x9 的數獨是否有效。只需要根據以下規則,驗證已經填入的數字是否有效即可。

  1. 數字 1-9 在每一行只能出現一次。
  2. 數字 1-9 在每一列只能出現一次。
  3. 數字 1-9 在每一個以粗實線分隔的 3x3 宮內只能出現一次。

img

上圖是一個部分填充的有效的數獨。

數獨部分空格內已填入了數字,空白格用 '.' 表示。

示例 1:

輸入:
[
  ["5","3",".",".","7",".",".",".","."],
  ["6",".",".","1","9","5",".",".","."],
  [".","9","8",".",".",".",".","6","."],
  ["8",".",".",".","6",".",".",".","3"],
  ["4",".",".","8",".","3",".",".","1"],
  ["7",".",".",".","2",".",".",".","6"],
  [".","6",".",".",".",".","2","8","."],
  [".",".",".","4","1","9",".",".","5"],
  [".",".",".",".","8",".",".","7","9"]
]
輸出: true

示例 2:

輸入:
[
  ["8","3",".",".","7",".",".",".","."],
  ["6",".",".","1","9","5",".",".","."],
  [".","9","8",".",".",".",".","6","."],
  ["8",".",".",".","6",".",".",".","3"],
  ["4",".",".","8",".","3",".",".","1"],
  ["7",".",".",".","2",".",".",".","6"],
  [".","6",".",".",".",".","2","8","."],
  [".",".",".","4","1","9",".",".","5"],
  [".",".",".",".","8",".",".","7","9"]
]
輸出: false
解釋: 除了第一行的第一個數字從 5 改爲 8 以外,空格內其他數字均與 示例1 相同。
     但由於位於左上角的 3x3 宮內有兩個 8 存在, 因此這個數獨是無效的。

說明:

  • 一個有效的數獨(部分已被填充)不一定是可解的。
  • 只需要根據以上規則,驗證已經填入的數字是否有效即可。
  • 給定數獨序列只包含數字 1-9 和字符 '.'
  • 給定數獨永遠是 9x9 形式的。

Answer

#
# @lc app=leetcode.cn id=36 lang=python3
#
# [36] 有效的數獨
#


# @lc code=start
class Solution:
    def isValidSudoku(self, board: List[List[str]]) -> bool:
        import numpy as np
        board = np.array(board)

        row = np.zeros((10, 10))
        column = np.zeros((10, 10))
        group = np.zeros((10, 10))

        for i in range(9):
            for j in range(9):
                if board[i, j] == '.':
                    continue
                num = int(board[i, j])
                if row[i][num] == 0 and column[j][num] == 0 and group[i // 3 * 3 + j // 3][num] == 0:
                    row[i][num] = 1
                    column[j][num] = 1
                    group[i // 3 * 3 + j // 3][num] = 1
                else:
                    return False

        return True


# @lc code=end

39 組合總和

Question

給定一個無重複元素的數組 candidates 和一個目標數 target ,找出 candidates 中所有可以使數字和爲 target 的組合。

candidates 中的數字可以無限制重複被選取。

說明:

  • 所有數字(包括 target)都是正整數。
  • 解集不能包含重複的組合。

示例 1:

輸入: candidates = [2,3,6,7], target = 7,
所求解集爲:
[
  [7],
  [2,2,3]
]

示例 2:

輸入: candidates = [2,3,5], target = 8,
所求解集爲:
[
  [2,2,2,2],
  [2,3,3],
  [3,5]
]

Answer

#
# @lc app=leetcode.cn id=39 lang=python3
#
# [39] 組合總和
#

# @lc code=start
class Solution:
    def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
        size = len(candidates)
        if size == 0:
            return []

        # 剪枝是爲了提速,在本題非必需
        candidates.sort()
        # 在遍歷的過程中記錄路徑,它是一個棧
        path = []
        res = []
        # 注意要傳入 size ,在 range 中, size 取不到
        self.__dfs(candidates, 0, size, path, res, target)
        return res

    def __dfs(self, candidates, begin, size, path, res, target):
        # 先寫遞歸終止的情況
        if target == 0:
            # Python 中可變對象是引用傳遞,因此需要將當前 path 裏的值拷貝出來
            # 或者使用 path.copy()
            res.append(path[:])
            return

        for index in range(begin, size):
            residue = target - candidates[index]
            # “剪枝”操作,不必遞歸到下一層,並且後面的分支也不必執行
            if residue < 0:
                break
            path.append(candidates[index])
            # 因爲下一層不能比上一層還小,起始索引還從 index 開始
            self.__dfs(candidates, index, size, path, res, residue)
            path.pop()


# @lc code=end


來自LeetCode題解

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章