[Swift]LeetCode636. 函數的獨佔時間 | Exclusive Time of Functions

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公衆號:山青詠芝(shanqingyongzhi)
➤博客園地址:山青詠芝(https://www.cnblogs.com/strengthen/
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址: http://www.javashuo.com/article/p-djtyocjo-me.html 
➤若是連接不是山青詠芝的博客園地址,則多是爬取做者的文章。
➤原文已修改更新!強烈建議點擊原文地址閱讀!支持做者!支持原創!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★html

Given the running logs of n functions that are executed in a nonpreemptive single threaded CPU, find the exclusive time of these functions.git

Each function has a unique id, start from 0 to n-1. A function may be called recursively or by another function.github

A log is a string has this format : function_id:start_or_end:timestamp. For example, "0:start:0" means function 0 starts from the very beginning of time 0. "0:end:0" means function 0 ends to the very end of time 0.數組

Exclusive time of a function is defined as the time spent within this function, the time spent by calling other functions should not be considered as this function's exclusive time. You should return the exclusive time of each function sorted by their function id.微信

Example 1:app

Input:
n = 2
logs = 
["0:start:0",
 "1:start:2",
 "1:end:5",
 "0:end:6"]
Output:[3, 4]
Explanation:
Function 0 starts at time 0, then it executes 2 units of time and reaches the end of time 1. 
Now function 0 calls function 1, function 1 starts at time 2, executes 4 units of time and end at time 5.
Function 0 is running again at time 6, and also end at the time 6, thus executes 1 unit of time. 
So function 0 totally execute 2 + 1 = 3 units of time, and function 1 totally execute 4 units of time. 

Note:ide

  1. Input logs will be sorted by timestamp, NOT log id.
  2. Your output should be sorted by function id, which means the 0th element of your output corresponds to the exclusive time of function 0.
  3. Two functions won't start or end at the same time.
  4. Functions could be called recursively, and will always end.
  5. 1 <= n <= 100

給出一個非搶佔單線程CPU的 n 個函數運行日誌,找到函數的獨佔時間。函數

每一個函數都有一個惟一的 Id,從 0 到 n-1,函數可能會遞歸調用或者被其餘函數調用。this

日誌是具備如下格式的字符串:function_id:start_or_end:timestamp。例如:"0:start:0" 表示函數 0 從 0 時刻開始運行。"0:end:0" 表示函數 0 在 0 時刻結束。spa

函數的獨佔時間定義是在該方法中花費的時間,調用其餘函數花費的時間不算該函數的獨佔時間。你須要根據函數的 Id 有序地返回每一個函數的獨佔時間。

示例 1:

輸入:
n = 2
logs = 
["0:start:0",
 "1:start:2",
 "1:end:5",
 "0:end:6"]
輸出:[3, 4]
說明:
函數 0 在時刻 0 開始,在執行了  2個時間單位結束於時刻 1。
如今函數 0 調用函數 1,函數 1 在時刻 2 開始,執行 4 個時間單位後結束於時刻 5。
函數 0 再次在時刻 6 開始執行,並在時刻 6 結束運行,從而執行了 1 個時間單位。
因此函數 0 總共的執行了 2 +1 =3 個時間單位,函數 1 總共執行了 4 個時間單位。

說明:

  1. 輸入的日誌會根據時間戳排序,而不是根據日誌Id排序。
  2. 你的輸出會根據函數Id排序,也就意味着你的輸出數組中序號爲 0 的元素至關於函數 0 的執行時間。
  3. 兩個函數不會在同時開始或結束。
  4. 函數容許被遞歸調用,直到運行結束。
  5. 1 <= n <= 100

168ms

 1 class Solution {
 2     func exclusiveTime(_ n: Int, _ logs: [String]) -> [Int] {
 3         var ans = [Int](repeating: 0, count: n)
 4         
 5         var stack = [Int]()
 6         var lastEndTime = 0
 7         for log in logs {
 8             let components = log.split(separator: ":")
 9             let id = Int(components[0])!
10             let isStart = components[1] == "start"
11             let currentTime = Int(components[2])!
12             
13             if isStart {
14                 if !stack.isEmpty {
15                     ans[stack.last!] += currentTime - lastEndTime
16                 }
17                 stack.append(id)
18                 lastEndTime = currentTime
19                 continue
20             } else {
21                 // this is a end of some task
22                 ans[stack.removeLast()] += currentTime - lastEndTime + 1
23                 lastEndTime = currentTime + 1
24             }            
25         }
26         return ans
27     }
28 }

172ms

 1 class Solution {
 2     func exclusiveTime(_ n: Int, _ logs: [String]) -> [Int] {
 3         var exclusiveTotals = [Int](repeating: 0, count: n)
 4         var startedTasks = [(id: Int, startTime: Int)]()
 5 
 6         for (id, status, time) in parsedLogs(logs) {
 7             if status == "start" {
 8 
 9                 // update exclusive time of parent task before this (if any)
10                 if let parentTask = startedTasks.last {
11                     exclusiveTotals[parentTask.id] += time - parentTask.startTime
12                 }
13 
14                 // push new task onto stack
15                 startedTasks.append((id: id, startTime: time))
16 
17 
18             } else if let previousTask = startedTasks.popLast() {
19 
20                 // update current ending task's exclusive time
21                 exclusiveTotals[previousTask.id] += time - previousTask.startTime + 1
22 
23                 // update parent task's start time (if any)
24                 if let parentTask = startedTasks.popLast() {
25                     startedTasks.append((id: parentTask.id, startTime: time+1))
26                 }
27             }
28         }
29 
30         return exclusiveTotals
31     }
32 
33     private func parsedLogs(_ logs: [String]) -> [(Int, String, Int)] {
34         return logs.map {
35             let tokens = $0.split(separator: ":")
36             return (Int(tokens[0])!, String(tokens[1]), Int(tokens[2])!)
37         }
38     }
39 }

180ms

 1 class Solution {    
 2     func exclusiveTime(_ n: Int, _ logs: [String]) -> [Int] {
 3         var result = Array(repeating: 0, count: n)
 4 
 5         let logRecords = logs.compactMap(parseLogString)
 6 
 7         guard logRecords.count > 1 else {
 8             return []
 9         }
10 
11         var lastRecord = logRecords[0]
12         var stack = [LogRecord]()
13         for logRecord in logRecords {
14             let offset: Int = {
15                 if lastRecord.type == .end && logRecord.type == .start {
16                     return -1
17                 } else if lastRecord.type == .start && logRecord.type == .end {
18                     return 1
19                 } else {
20                     return 0
21                 }
22             }()
23 
24             let timeDiff = logRecord.time - lastRecord.time + offset
25             if logRecord.type == .start {
26                 // push on to the stack
27                 if let topRecord = stack.last {
28                     result[topRecord.id] += timeDiff
29                 }
30                 stack.append(logRecord)
31             } else if logRecord.type == .end {
32                 if let topRecord = stack.popLast() {
33                     if topRecord.id != logRecord.id || topRecord.type != .start {
34                         assertionFailure("input not correctly formatted")
35                         return []
36                     }
37 
38                     result[topRecord.id] += timeDiff
39                 } else {
40                     assertionFailure("input not correctly formatted")
41                     return []
42                 }
43             }
44 
45             lastRecord = logRecord
46         }
47 
48         return result
49     }
50 
51     enum LogType: String {
52         case start = "start"
53         case end = "end"
54     }
55 
56     struct LogRecord {
57         var id: Int
58         var type: LogType
59         var time: Int
60         init(id: Int, type: LogType, time: Int) {
61             self.id = id
62             self.type = type
63             self.time = time
64         }
65     }
66 
67     func parseLogString(_ logString: String) -> LogRecord? {
68         guard !logString.isEmpty else {
69             return nil
70         }
71 
72         let components = logString.split(separator: ":")
73         guard components.count == 3 else {
74             return nil
75         }
76 
77         guard let id = Int(String(components[0])) else {
78             return nil
79         }
80 
81         guard let type = LogType(rawValue: String(components[1])) else {
82             return nil
83         }
84 
85         guard let time = Int(String(components[2])) else {
86             return nil
87         }
88 
89         return LogRecord(id: id, type: type, time: time)
90     }    
91 }

188ms

 1 class Solution {
 2     func exclusiveTime(_ n: Int, _ logs: [String]) -> [Int] {
 3         var stack = [Int]()
 4         var res = Array(repeating: 0, count: n)
 5         var s = logs[0].split(separator: ":")
 6         stack.append(Int(s[0])!)
 7         var i = 1
 8         var prev = Int(s[2])
 9         while i < logs.count {
10             s = logs[i].split(separator: ":")
11             if s[1] == "start" {
12                 if !stack.isEmpty {
13                     let index = stack.last!
14                     let val = res[index]
15                     res[index] = val + Int(s[2])! - prev!
16                 }
17                 stack.append(Int(s[0])!)
18                 prev = Int(s[2])
19             } else {
20                 let index = stack.last!
21                 res[index] = res[index] + Int(s[2])! - prev! + 1
22                 stack.removeLast()
23                 prev = Int(s[2])! + 1
24             }
25             i += 1
26         }
27         return res
28     }
29 }

Runtime: 208 ms
Memory Usage: 20 MB
 1 class Solution {
 2     func exclusiveTime(_ n: Int, _ logs: [String]) -> [Int] {
 3         var stack = [Int]()
 4         var pre = 0
 5         var res = Array(repeating: 0, count: n)
 6         
 7         for log in logs {
 8             
 9             let tokens = log.components(separatedBy: ":")
10             
11             let id = Int(tokens[0])!
12             let act = tokens[1]
13             let time = Int(tokens[2])!
14             
15             if act == "start" {
16                 
17                 if !stack.isEmpty {
18                     
19                     let top = stack[stack.count - 1]
20                     res[top] += time - pre
21                 }
22                 
23                 stack.append(id)
24                 pre = time
25                 
26             } else {
27                 
28                 res[stack.removeLast()] += time - pre + 1
29                 pre = time + 1
30             }
31         }        
32         return res
33     }
34 }

232ms

 1 class Solution {
 2 func exclusiveTime(_ n: Int, _ logs: [String]) -> [Int] {
 3     var result = Array(repeating: 0, count: n)
 4     
 5     var funcStack = [Int]()
 6     var prev = 0
 7     
 8     for s in logs {
 9         let fId = Int(s.prefix(upTo: s.firstIndex(of: ":")!))!
10         let time = Int(s.suffix(from: s.index(after: s.lastIndex(of: ":")!)))!
11         
12         if s.contains("start") {
13             if let last = funcStack.last {
14                 result[last] += time - prev
15             }
16             
17             prev = time
18             funcStack.append(fId)
19         } else {
20             if let last = funcStack.last {
21                 result[last] += time - prev + 1
22                 funcStack.removeLast()
23                 prev = time + 1
24             }
25         }
26     }
27     return result
28    }
29 }

248ms

 1 class Solution {
 2     func exclusiveTime(_ n: Int, _ logs: [String]) -> [Int] {
 3         var stack: [Int] = [] // store the function id
 4         var res: [Int] = Array(repeating: 0, count: n)
 5         var pre: Int = 0
 6         for log in logs {
 7             let l = log.components(separatedBy: ":")
 8             let id = Int(l[0])!
 9             let curr = Int(l[2])!
10             if l[1] == "start" {
11                 if !stack.isEmpty {
12                     res[stack.last!] += curr - pre
13                 }
14                 stack.append(id)
15                 pre = curr
16             } else {
17                 res[stack.last!] += (curr - pre + 1)
18                 stack.removeLast()
19                 pre = curr + 1
20             }
21         }        
22         return res
23     }
24 }

252ms

 1 class Solution {
 2     func exclusiveTime(_ n: Int, _ logs: [String]) -> [Int] {
 3 
 4         if n == 0 || logs.count == 0 { return [] }
 5         var tuples = [(Int, Bool, Int)]()
 6         logs.forEach {
 7             let vals = $0.components(separatedBy: ":")
 8             let id = Int(vals[0])!
 9             let isStart = vals[1] == "start"
10             let time = Int(vals[2])!
11             tuples.append((id, isStart, time))
12         }
13         
14         var result = [Int](repeating: 0, count: n)
15         var stack = [(Int, Bool, Int)]()
16         var lastTime = 0
17         
18         tuples.forEach {
19             if $0.1 {
20                 if !stack.isEmpty {
21                     let last = stack.last!
22                     let time = $0.2 - lastTime
23                     result[last.0] += time
24                 }
25                 lastTime = $0.2
26                 stack.append($0)
27             } else {
28                 let last = stack.removeLast()
29                 let time = $0.2 - lastTime + 1
30                 result[last.0] += time
31                 lastTime = $0.2 + 1
32             }
33         }        
34         return result
35     }
36 }

256ms

 1 class Solution {
 2     func exclusiveTime(_ n: Int, _ logs: [String]) -> [Int] {
 3         guard n != 0 && logs.count > 0 else {return []}
 4         var times = [Int](repeating: 0, count: n)
 5         
 6         var st = [(op: Int, runtime: Int)]()
 7         for log in logs {
 8             let comp = log.components(separatedBy: ":")
 9             guard comp.count == 3 else {continue}
10             guard let op = Int(comp[0]), let currTime = Int(comp[2]) else {continue}
11             
12             
13             if comp[1] == "start" {
14                 if st.count > 0 {
15                     let currTop = st.last!
16                     times[currTop.op] += currTime - st[st.count - 1].runtime
17                 }
18                 st.append((op, currTime))
19             } else {
20                 if st.count == 0 || st.last!.op != op {return []}
21                 let currTop = st.removeLast()
22                 times[currTop.op] += currTime - currTop.runtime + 1
23                 if st.count > 0 {
24                     st[st.count - 1].runtime = currTime + 1
25                 }
26             }            
27         }
28         return times
29     }
30 }

276ms

 1 class Solution {
 2     func exclusiveTime(_ n: Int, _ logs: [String]) -> [Int] {
 3         var stack = [(Int, Int)]()
 4         var ans = [Int](repeating: 0, count: n)
 5         for i in 0..<logs.count {
 6             let components = logs[i].components(separatedBy: ":")
 7             let timestamp = Int(components[2])!
 8             let functionID = Int(components[0])!
 9             let functionState = components[1]
10             
11             if functionState == "start" {
12                 if let last = stack.last { // Count the last run
13                     ans[last.0] += (timestamp - last.1) // timestamp is not inclusive
14                 }
15                 stack.append((functionID, timestamp))
16             } else {
17                 let last = stack.removeLast()
18                 ans[functionID] += (timestamp - last.1 + 1) // timestamp is inclusive
19                 if let last = stack.last { // Update the last timestamp
20                     stack.removeLast()
21                     stack.append((last.0, timestamp + 1))
22                 }
23             }
24         }
25         return ans
26     }
27 }

284ms

 1 class Solution {    
 2     func parseString(_ log: String) -> (Int, Int, Bool) {
 3         let start = ":start:"
 4         let end = ":end:"
 5         var separator = ""
 6         if log.contains(start) {
 7             let nums = log.components(separatedBy: start).compactMap { Int($0) }
 8             return (nums[0], nums[1], true)
 9         } else {
10             let nums = log.components(separatedBy: end).compactMap { Int($0) }
11             return (nums[0], nums[1], false)
12         }
13     }
14     
15     func exclusiveTime(_ n: Int, _ logs: [String]) -> [Int] {
16         var stack = [Int]()
17         var exclusiveTime = Array(repeating: 0, count: n)
18         var lastTimestamp = 0
19         for log in logs {
20             let (id, time, isStart) = parseString(log)
21             if let lastId = stack.last {
22                 exclusiveTime[lastId] += time - lastTimestamp
23                 if !isStart {
24                     exclusiveTime[lastId] += 1
25                 }
26             }
27             lastTimestamp = time
28             if isStart {
29                 stack.append(id)
30             } else {
31                 stack.removeLast()
32                 lastTimestamp += 1
33             }
34         }
35         return exclusiveTime
36     }
37 }

296ms

 1 class Solution {
 2     func exclusiveTime(_ n: Int, _ logs: [String]) -> [Int] {
 3         var res = Array(repeating: 0, count: n)
 4         var currRunning: Int?
 5         var currStart: Int=0
 6         var callStack = [Int]()
 7         for log in logs {
 8             let component = log.components(separatedBy: ":")
 9             let funcID = Int(component[0])!
10             let funcTime = Int(component[2])!
11             let isStart = (component[1] == "start")
12             if isStart {
13                 
14                 if currRunning != nil {
15                     res[currRunning!]+=funcTime-currStart
16                 }
17                     currRunning = funcID
18                     currStart = funcTime
19                     callStack.append(funcID)
20                 //} else {
21                     //recursive, dont need to update
22                 //}
23                 
24                 
25             } else { //end
26                 guard funcID == callStack.last! else { return [] }
27                 if let currRunning = currRunning {
28                     res[currRunning]+=funcTime-currStart+1
29                 }
30                 callStack = Array(callStack.dropLast())
31                 currRunning = callStack.last
32                 currStart = funcTime+1
33             }
34         }
35         return res
36     }
37 }
相關文章
相關標籤/搜索