题目描述: 请根据每日 气温 列表,重新生成一个列表。对应位置的输出为:要想观测到更高的气温,至少需要等待的天数。如果气温在这之后都不会升高,请在该位置用 0 来代替。
示例:
给定一个列表 temperatures = [73, 74, 75, 71, 69, 72, 76, 73],
你的输出应该是 [1, 1, 4, 2, 1, 1, 0, 0]。
提示:气温 列表长度的范围是 [1, 30000]。每个气温的值的均为华氏度,都是在 [30, 100] 范围内的整数。
解题开发语言:Swift
题解一:倒叙遍历(记录温度值出现的最新位置)
解题思路:倒序遍历数组,创建一个默认值为Int.max,长度为100的数组next,在遍历数组的过程中用于保存对应摄氏度最近一次出现在数组中的下标位置,外层遍历时,内部通过T[i]+1..<101进行内部遍历next,寻找距离当前i最近的已存储的next中的index, 如果index存在,result[i]=index-i,直至遍历结束。
class Solution {
func dailyTemperatures(_ T: [Int]) -> [Int] {
var result = [Int](repeating: 0, count: T.count)
var next = [Int](repeating: Int.max, count: 101)
for i in (0..<T.count).reversed() {
var index = Int.max
for j in T[i]+1..<101 {
if (next[j] < index) {
index = next[j]
}
}
if index < Int.max {
result[i] = index - i
}
next[T[i]] = i
}
return result
}
}
复杂度分析
时间复杂度:O(nm), n为数组长度,m为数组next长度,在本题中温度不超过 100,所以 m 的值为 100。反向遍历温度列表一遍,对于温度列表中的每个值,都要遍历数组 next 一遍。
空间复杂度:O(m), m为next数组长度,除了返回值以外,需要维护长度为 m的数组 next 记录每个温度第一次出现的下标位置。
题解二:正序遍历(使用数组保存当前温度值的数据)
解题思路:正序遍历,将当前温度与temp数组中的尾部数据一次比较,如果数组数据小于当前温度值,记录下标差,数组删除尾部数据,比较下一个尾部数据,直至尾部数据为空或者小于等于当前温度,结束for循环后,对temp数组中的数据(观测到更高的气温)进行置0操作。
class Solution {
func dailyTemperatures(_ T: [Int]) -> [Int] {
var result = [Int](repeating: 0, count: T.count)
var temp = [(Int, Int)]()
for i in 0..<T.count {
let val = T[i]
var tempLast = temp.last
while(tempLast != nil && tempLast!.1 < val) {
result[tempLast!.0] = i - tempLast!.0
temp.removeLast()
tempLast = temp.last
}
temp.append((i, val))
}
var tempLast = temp.last
while (tempLast != nil) {
result[tempLast!.0] = 0
temp.removeLast()
tempLast = temp.last
}
return result
}
}
复杂度分析
时间复杂度:O(n), n为数组长度,题解中的两个while循环在整个运算过程中加在一起执行n次,所以时间复杂度为O(2n), 忽略乘数因子,时间复杂度为O(n)。
空间复杂度:O(n), n为temp数组长度,除了返回值以外,需要维护平均长度为 n的数组 temp 记录每个温度数据(温度值+下标)。注:n = (1+2+...+n)/n
题解三:递减栈(正序遍历,使用栈保存当前温度值的数据)
解题思路:正序遍历,将当前温度与栈顶温度值进行比较,栈顶温度 < 当前温度,数据出栈,直至 栈顶温度 >= 当前温度 或 栈为空,然后将当前温度入栈,继续遍历,直至遍历完成
struct MutableArrayStack {
var dataList: [(Int, Int)] = []
var n: Int = 0
var count: Int = 0
// 栈顶元素
public var stackTop: (Int, Int)? {
if count == 0 {
return nil
}
return dataList[count-1]
}
init(num: Int) {
n = num
count = 0
dataList = [(Int, Int)](repeating: (-1, -1), count: num);
}
public mutating func push(_ item: (Int, Int)) -> Bool {
if count == n {
reSize()
}
dataList[count] = item
count += 1
return true
}
public mutating func pop() -> (Int, Int)? {
if count == 0 {
return nil
}
let val = dataList[count-1]
count -= 1
return val
}
private mutating func reSize() {
var newAry = [(Int, Int)](repeating: (-1,-1), count: 2 * n)
let range = newAry.startIndex..<newAry.index(newAry.startIndex, offsetBy: n)
newAry.replaceSubrange(range, with: dataList)
dataList = newAry
n = 2 * n
}
}
class Solution {
func dailyTemperatures(_ T: [Int]) -> [Int] {
var result = [Int](repeating: 0, count: T.count)
var stack = MutableArrayStack(num: 20)
for i in 0..<T.count {
let val = T[i]
var stackTop = stack.pop()
if stackTop == nil {
stack.push((i,val))
} else {
while(stackTop != nil && stackTop!.1 < val) {
result[stackTop!.0] = i - stackTop!.0
stackTop = stack.pop()
}
if stackTop != nil {
stack.push(stackTop!)
}
stack.push((i, val))
}
}
return result
}
}
复杂度分析
时间复杂度:O(n), n为数组长度,while循环在整个for循环中最多可能执行n-1次,所以时间复杂度为O(n+n-1), 忽略乘数因子,时间复杂度为O(n)。
空间复杂度:O(n), n为数组长度,除了返回值以外,需要维护平均长度为n的栈stack, 记录每个温度数据(温度值+下标)。注:n = (1+2+...+(n-1))/n