第十週LeetCode記錄
11.18 46. 拼接最大數
給定長度分別為 m 和 n 的兩個陣列,其元素由 0-9 構成,表示兩個自然數各位上的數字。現在從這兩個陣列中選出 k (k <= m + n) 個數字拼接成一個新的數,要求從同一個陣列中取出的數字保持其在原陣列中的相對順序。
求滿足該條件的最大數。結果返回一個表示該最大數的長度為 k 的陣列。
輸入: nums1 = [3, 4, 6, 5] nums2 = [9, 1, 2, 5, 8, 3] k = 5 輸出: [9, 8, 6, 5, 3] 輸入: nums1 = [6, 7] nums2 = [6, 0, 4] k = 5 輸出: [6, 7, 6, 0, 4]
最優解
class Solution: def maxNumber(self, nums1, nums2, k): def pick_max(nums, k): stack = [] drop = len(nums) - k for num in nums: while drop and stack and stack[-1] < num: stack.pop() drop -= 1 stack.append(num) return stack[:k] def merge(A, B): ans = [] while A or B: bigger = A if A > B else B ans.append(bigger[0]) bigger.pop(0) return ans return max(merge(pick_max(nums1, i), pick_max(nums2, k-i)) for i in range(k+1) if i <= len(nums1) and k-i <= len(nums2))
總結
從2個數組共取k個數字,遍歷各種情況。分治解決
pick_max是從nums數組裡取前k位組成新的陣列,merge是將兩數組合併為最大陣列
思考一下時間複雜度和空間複雜度是多少
11.19 47. 不同字元的最小子序列
返回字串 text
中按字典序排列最小的子序列,該子序列包含 text
中所有不同字元一次。
輸入:"cdadabcc"
輸出:"adbc"
輸入:"abcd"
輸出:"abcd"
輸入:"ecbacba"
輸出:"eacb"
輸入:"leetcode"
輸出:"letcod"
思路
跟上面的題型一樣,利用棧來解
我的解
class Solution: def smallestSubsequence(self, s: str) -> str: from collections import Counter s_dic = Counter(s) stack = [] for i in s: if i not in stack: while stack and stack[-1] >= i and s_dic[stack[-1]] > 0: stack.pop() stack.append(i) s_dic[i] -= 1 return ''.join(stack)
11.20 48. 對稱的二叉樹
請實現一個函式,用來判斷一棵二叉樹是不是對稱的。如果一棵二叉樹和它的映象一樣,那麼它是對稱的。
例如,二叉樹 [1,2,2,3,4,4,3] 是對稱的。
1
/ \
2 2
/ \ / \
3 4 4 3
但是下面這個 [1,2,2,null,3,null,3] 則不是映象對稱的:
1
/ \
2 2
\ \
3 3
最優解
class Solution:
@classmethod
def isSymmetric(self, root: TreeNode) -> bool:
def recrue(Left,Right):
if not Left and not Right:
return True
if not Left or not Right or Left.val != Right.val:
return False
return recrue(Left.left,Right.right) and recrue(Left.right,Right.left)
return recrue(root.left,root.right) if root else True
總結
和29題 另一個樹的子樹同樣的方法,遞迴遍歷對稱樹的定義即可。
11.21 49.最接近原點的k個點
我們有一個由平面上的點組成的列表 points。需要從中找出 K 個距離原點 (0, 0) 最近的點。
(這裡,平面上兩點之間的距離是歐幾里德距離。)
你可以按任何順序返回答案。除了點座標的順序之外,答案確保是唯一的。
輸入:points = [[1,3],[-2,2]], K = 1
輸出:[[-2,2]]
解釋:
(1, 3) 和原點之間的距離為 sqrt(10),
(-2, 2) 和原點之間的距離為 sqrt(8),
由於 sqrt(8) < sqrt(10),(-2, 2) 離原點更近。
我們只需要距離原點最近的 K = 1 個點,所以答案就是 [[-2,2]]。
輸入:points = [[3,3],[5,-1],[-2,4]], K = 2
輸出:[[3,3],[-2,4]]
(答案 [[-2,4],[3,3]] 也會被接受。)
思路
遍歷每個點,排序取前k。
我的解
class Solution:
def kClosest(self, points: List[List[int]], K: int) -> List[List[int]]:
import math
def calc_dis(point):
x, y = point
return math.sqrt(x ** 2 + y ** 2)
return sorted(points,key=lambda k:calc_dis(k))[:K]
最優解
優先佇列
我們可以使用一個優先佇列(大根堆)實時維護前 KK 個最小的距離平方。
首先我們將前 KK 個點的編號(為了方便最後直接得到答案)以及對應的距離平方放入優先佇列中,隨後從第 K+1K+1 個點開始遍歷:如果當前點的距離平方比堆頂的點的距離平方要小,就把堆頂的點彈出,再插入當前的點。當遍歷完成後,所有在優先佇列中的點就是前 KK 個距離最小的點。
class Solution:
def kClosest(self, points: List[List[int]], K: int) -> List[List[int]]:
q = [(-x ** 2 - y ** 2, i) for i, (x, y) in enumerate(points[:K])]
heapq.heapify(q)
n = len(points)
for i in range(K, n):
x, y = points[i]
dist = -x ** 2 - y ** 2
heapq.heappushpop(q, (dist, i))
ans = [points[identity] for (_, identity) in q]
return ans
總結
取前幾個後幾個的題型,優先想到用堆處理。
11.23 50. 最大二叉樹
給定一個不含重複元素的整數陣列。一個以此陣列構建的最大二叉樹定義如下:
二叉樹的根是陣列中的最大元素。
左子樹是通過陣列中最大值左邊部分構造出的最大二叉樹。
右子樹是通過陣列中最大值右邊部分構造出的最大二叉樹。
通過給定的陣列構建最大二叉樹,並且輸出這個樹的根節點。
輸入:[3,2,1,6,0,5]
輸出:返回下面這棵樹的根節點:
6
/ \
3 5
\ /
2 0
\
1
最優解
public class Solution {
public TreeNode constructMaximumBinaryTree(int[] nums) {
return construct(nums, 0, nums.length);
}
public TreeNode construct(int[] nums, int l, int r) {
if (l == r)
return null;
int max_i = max(nums, l, r);
TreeNode root = new TreeNode(nums[max_i]);
root.left = construct(nums, l, max_i);
root.right = construct(nums, max_i + 1, r);
return root;
}
public int max(int[] nums, int l, int r) {
int max_i = l;
for (int i = l; i < r; i++) {
if (nums[max_i] < nums[i])
max_i = i;
}
return max_i;
}
}
總結
遞迴處理。每次處理最左最右最大。