1.最近的請求次數,屬于窗口類題型,都是使用隊列把前面不符合的去掉,再進行計算剩下的
int ping(int t) 在時間 t 添加一個新請求,其中 t 表示以毫秒為單位的某個時間,并返回過去 3000 毫秒內發生的所有請求數(包括新請求)。確切地說,返回在 [t-3000, t] 內發生的請求數。
解法:通過保持數據都是3000毫秒內的數據進行計數,換句話說就是每次 新t進來,就把3000毫秒外的刪除。
用隊列解決:
class RecentCounter {
var queue = [Int]()
init() {
}
func ping(_ t: Int) -> Int {
if queue.count == 0 {
return 1
}
while queue.first! > t - 3000 {
queue.removeFirst()
}
return queue.count
}
}
用數組的官方方法解決:時間為100%,內存77%
var array = [Int]()
init() {
}
func ping(_ t: Int) -> Int {
array.removeAll {$0 < t - 3000 }
array.append(t)
return array.count
}
2.[無法吃午餐的學生數量]
學校的自助午餐提供圓形和方形的三明治,分別用數字 0 和 1 表示。所有學生站在一個隊列里,每個學生要么喜歡圓形的要么喜歡方形的。
餐廳里三明治的數量與學生的數量相同。所有三明治都放在一個 棧 里,每一輪:
如果隊列最前面的學生 喜歡 棧頂的三明治,那么會 拿走它 并離開隊列。
否則,這名學生會 放棄這個三明治 并回到隊列的尾部。
這個過程會一直持續到隊列里所有學生都不喜歡棧頂的三明治為止。
給你兩個整數數組 students 和 sandwiches ,其中 sandwiches[i] 是棧里面第 i 個三明治的類型(i = 0 是棧的頂部), students[j] 是初始隊列里第 j 名學生對三明治的喜好(j = 0 是隊列的最開始位置)。請你返回無法吃午餐的學生數量。
解法:把喜歡吃午餐的學生分類,得到每類學生的個數,數組/字典表示,然后根據遍歷三文治,根據元素把響應學生減少,直到一類學生個數為0,說明此輪此類三文治還有,但學生上輪已經輪完,沒有了,那說明此類三文治已經無法被選完,所以說明游戲已經到了結束的時候,那這時可以返回各類學生的個數,也就是無法吃午餐的學生數。
數組解法:時間空間雙100%。
func countStudents(_ students: [Int], _ sandwiches: [Int]) -> Int {
// 分兩類學生,喜歡圓形/方形
var stuLike = [Int](repeating: 0, count: 2)
for x in students {
// 把所有學生遍歷分類
stuLike[x] += 1
}
// 把三文治遍歷,通過對應0,1 獲取對應學生進行匹配減少
for y in sandwiches {
// 當其中一類學生為0,說明三文治還有,但喜歡此類別的學生已經沒有了,說明三文治肯定無法被調完,退出遍歷
if stuLike[y] == 0 {
break
}
stuLike[y] -= 1
}
// 此時返回的就是最終無法挑中喜歡三文治的兩類學生總數
return stuLike[0] + stuLike[1]
}
字典解法,時間為33%,空間33%,不是最佳解法。
func countStudents(_ students: [Int], _ sandwiches: [Int]) -> Int {
if students.count == 0 {
return 0
}
var map = [Int: Int]()
// 需要初始化兩類為0
map[0] = 0
map[1] = 0
for student in students {
map[student]! += 1
}
for san in sandwiches {
if map[san] == 0 {
break
}
map[san]! -= 1
}
return (map[0] ?? 0) + (map[1] ?? 0)
}