为有牺牲多壮志,敢教日月换新天。

[Swift]LeetCode990. 等式方程的可满足性 | Satisfiability of Equality Equations

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公众号:山青咏芝(shanqingyongzhi)
➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址:https://www.cnblogs.com/strengthen/p/10361525.html 
➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。
➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

热烈欢迎,请直接点击!!!

进入博主App Store主页,下载使用各个作品!!!

注:博主将坚持每月上线一个新app!!!

Given an array equations of strings that represent relationships between variables, each string equations[i] has length 4and takes one of two different forms: "a==b" or "a!=b".  Here, a and b are lowercase letters (not necessarily different) that represent one-letter variable names.

Return true if and only if it is possible to assign integers to variable names so as to satisfy all the given equations.

Example 1:

Input: ["a==b","b!=a"]
Output: false
Explanation: If we assign say, a = 1 and b = 1, then the first equation is satisfied, but not the second.  There is no way to assign the variables to satisfy both equations.

Example 2:

Input: ["b==a","a==b"]
Output: true
Explanation: We could assign a = 1 and b = 1 to satisfy both equations.

Example 3:

Input: ["a==b","b==c","a==c"]
Output: true

Example 4:

Input: ["a==b","b!=c","c==a"]
Output: false

Example 5:

Input: ["c==c","b==d","x!=z"]
Output: true

Note:

  1. 1 <= equations.length <= 500
  2. equations[i].length == 4
  3. equations[i][0] and equations[i][3] are lowercase letters
  4. equations[i][1] is either '=' or '!'
  5. equations[i][2] is '='

给定一个由表示变量之间关系的字符串方程组成的数组,每个字符串方程 equations[i] 的长度为 4,并采用两种不同的形式之一:"a==b" 或 "a!=b"。在这里,a 和 b 是小写字母(不一定不同),表示单字母变量名。

只有当可以将整数分配给变量名,以便满足所有给定的方程时才返回 true,否则返回 false。 

示例 1:

输入:["a==b","b!=a"]
输出:false
解释:如果我们指定,a = 1 且 b = 1,那么可以满足第一个方程,但无法满足第二个方程。没有办法分配变量同时满足这两个方程。

示例 2:

输出:["b==a","a==b"]
输入:true
解释:我们可以指定 a = 1 且 b = 1 以满足满足这两个方程。

示例 3:

输入:["a==b","b==c","a==c"]
输出:true

示例 4:

输入:["a==b","b!=c","c==a"]
输出:false

示例 5:

输入:["c==c","b==d","x!=z"]
输出:true

提示:

  1. 1 <= equations.length <= 500
  2. equations[i].length == 4
  3. equations[i][0] 和 equations[i][3] 是小写字母
  4. equations[i][1] 要么是 '=',要么是 '!'
  5. equations[i][2] 是 '='

Runtime: 48 ms

Memory Usage: 4 MB

  1 class Solution {
  2     func equationsPossible(_ equations: [String]) -> Bool {
  3         var ds:DJSet = DJSet(26)
  4         for e in equations
  5         {
  6             if e[1] == "="
  7             {
  8                 var l:Int = e[0].ascii - 97
  9                 var r:Int = e[3].ascii - 97
 10                 ds.union(l,r)
 11             }
 12         }
 13         for e in equations
 14         {
 15             if e[1] == "!"
 16             {
 17                 var l:Int = e[0].ascii - 97
 18                 var r:Int = e[3].ascii - 97
 19                 if ds.equiv(l,r)
 20                 {
 21                     return false
 22                 }
 23             } 
 24         }
 25         return true
 26     }
 27 }
 28 
 29 extension String {        
 30     //subscript函数可以检索数组中的值
 31     //直接按照索引方式截取指定索引的字符
 32     subscript (_ i: Int) -> Character {
 33         //读取字符
 34         get {return self[index(startIndex, offsetBy: i)]}
 35     }
 36 }
 37 
 38 extension Character  
 39 {  
 40   //属性:ASCII整数值(定义小写为整数值)
 41    var ascii: Int {
 42         get {
 43             let s = String(self).unicodeScalars
 44             return Int(s[s.startIndex].value)
 45         }
 46     }
 47 }
 48 
 49 public class DJSet
 50 {
 51     var upper:[Int]
 52     
 53     init(_ n:Int)
 54     {
 55         upper = [Int](repeating:-1,count:n)
 56     }
 57     
 58     func root(_ x:Int) -> Int
 59     {
 60         if(upper[x] < 0)
 61         {
 62             return x
 63         }
 64         else
 65         {
 66             upper[x] = root(upper[x])
 67             return upper[x]
 68         }
 69     }
 70     
 71     func equiv(_ x:Int,_ y:Int) -> Bool
 72     {
 73         return root(x) == root(y)
 74     }
 75     
 76     func union(_ x:Int,_ y:Int) -> Bool
 77     {
 78         var x:Int = root(x)
 79         var y:Int = root(y)
 80         if x != y
 81         {
 82             if upper[y] < upper[x]
 83             {
 84                 var d:Int = x
 85                 x = y
 86                 y = d
 87             }
 88             upper[x] += upper[y]
 89             upper[y] = x
 90         }
 91         return x == y
 92     }
 93     
 94     func count() -> Int
 95     {
 96         var ct:Int = 0
 97         for u in upper
 98         {
 99             if u < 0
100             {
101                 ct += 1
102             }
103         }
104         return ct
105     }
106 }

52ms
  1 class Solution {
  2     
  3     typealias Equation = (var1: Character, var2: Character, areEqual: Bool)
  4 
  5     func equationsPossible(_ equations: [String]) -> Bool {
  6         var equalHashMap = [Character: Character]()
  7 
  8         let equations = parseEquations(equations)
  9 
 10         // process equality conditions using union-finding algorithm
 11         // process inequality conditions
 12 
 13         let equalityEquations = equations.filter { $0.areEqual }
 14         let inEqualityEquations = equations.filter { !$0.areEqual }
 15 
 16         // similar union finding algorithm
 17         for equation in equalityEquations {
 18             let var1 = equation.var1
 19             let var2 = equation.var2
 20             if equalHashMap[var1] == nil && equalHashMap[var2] == nil {
 21                 equalHashMap[var1] = var1
 22                 equalHashMap[var2] = var1
 23             } else if equalHashMap[var1] == nil {
 24                 equalHashMap[var1] = findParent(var2, equalHashMap)
 25             } else { // equalHashMap[var2] == nil
 26                 equalHashMap[var2] = findParent(var1, equalHashMap)
 27             }
 28         }
 29 
 30         for equation in inEqualityEquations {
 31             let var1 = equation.var1
 32             let var2 = equation.var2
 33             let parentVar1 = equalHashMap[var1] ?? var1
 34             let parentVar2 = equalHashMap[var2] ?? var2
 35             if parentVar1 == parentVar2 {
 36                 return false
 37             }
 38         }
 39 
 40         return true
 41     }
 42 
 43     func findParent(_ ch: Character, _ hashMap: [Character: Character]) -> Character {
 44         var result = hashMap[ch] ?? ch
 45         while let parent = hashMap[result], parent != result {
 46             result = parent
 47         }
 48         return result
 49     }
 50 
 51     func parseEquations(_ equations: [String]) -> [Equation] {
 52         return equations.map { parseString($0) }
 53     }
 54 
 55     func parseString(_ string: String) -> Equation {
 56         guard string.count == 4 else {
 57             assertionFailure("input string: \(string) not in correct format")
 58             return ("a", "a", false)
 59         }
 60 
 61         let var1 = string[0]
 62         let areEqual = string.subString(from: 1, to: 2) == "==" ? true : false
 63         let var2 = string[3]
 64         return (var1, var2, areEqual)
 65     }
 66     
 67 }
 68 
 69 extension String {
 70 
 71     subscript(i: Int) -> Character {
 72         get {
 73             return self[index(startIndex, offsetBy: i)]
 74         }
 75     }
 76     
 77     func subString(from: Int, to: Int) -> String {
 78         guard from <= to else {
 79             return ""
 80         }
 81         
 82         let startIndex = self.index(self.startIndex, offsetBy: from)
 83         let endIndex = self.index(self.startIndex, offsetBy: to)
 84         return String(self[startIndex...endIndex])
 85     }
 86     
 87     func subString(from: Int) -> String {
 88         let startIndex = self.index(self.startIndex, offsetBy: from)
 89         return String(self.suffix(from: startIndex))
 90     }
 91     
 92     func asciiValues() -> [Int] {
 93         return Array(self.utf16).map { Int($0) }
 94     }
 95     
 96     mutating func lTrim(_ regex: String = "^\\s+") {
 97         if let trailingSpacesRange = self.range(of: regex, options: .regularExpression) {
 98             self.replaceSubrange(trailingSpacesRange, with: "")
 99         }
100     }
101     
102     mutating func rTrim(_ regex: String = "\\s+$") {
103         if let trailingSpacesRange = self.range(of: regex, options: .regularExpression) {
104             self.replaceSubrange(trailingSpacesRange, with: "")
105         }
106     }
107 
108     func stringByReplacingAt(_ index: Int, with ch: Character) -> String {
109         var chars = Array(self)
110         chars[index] = ch
111         let modifiedString = String(chars)
112         return modifiedString
113     }
114 }

56ms

 1 class Solution {
 2     func equationsPossible(_ equations: [String]) -> Bool {
 3         let unionFind = UnionFind.init(26)
 4         let equalUnion = equations.filter { $0[1] == "=" }
 5         let notEqualUnion = equations.filter { $0[1] == "!" }
 6         let startingValue = Character("a").ascii!
 7         for item in equalUnion {
 8             let left = Int(item[0].ascii! - startingValue)
 9             let right = Int(item[3].ascii! - startingValue)
10             unionFind.union(left, right)
11         }
12 
13         for item in notEqualUnion {
14             let left = Int(item[0].ascii! - startingValue)
15             let right = Int(item[3].ascii! - startingValue)
16             if unionFind.find(left) == unionFind.find(right) {
17                 return false
18             }
19         }
20         return true
21     }
22 }
23 
24 extension String {
25     subscript (i: Int) -> Character {
26         return self[index(startIndex, offsetBy: i)]
27     }
28 }
29 
30 extension Character {
31     var isAscii: Bool {
32         return unicodeScalars.first?.isASCII == true
33     }
34     var ascii: UInt32? {
35         return isAscii ? unicodeScalars.first?.value : nil
36     }
37 }
38 
39 class UnionFind {
40     var root = [Int]()
41     var rank = [Int]()
42     
43     public init(_ n: Int) {
44         // if root is not initialized, 'self' captured by a closure before all members were initialized
45         (0...n-1).forEach { root.append($0) }
46         rank = [Int](repeating: 1, count: n)
47     }
48     
49     fileprivate func find(_ current: Int) -> Int {
50         var path = [Int]()
51         var current = current
52         while root[current] != current {
53             path.append(current)
54             current = root[current]
55         }
56         
57         for p in path {
58             root[p] = current
59         }
60         return current
61     }
62     
63     public func union(_ x: Int, _ y: Int) {
64         let xRoot = find(x)
65         let yRoot = find(y)
66         
67         if xRoot == yRoot {
68             return
69         }
70         if rank[xRoot] > rank[yRoot] {
71             root[yRoot] = xRoot
72         } else if rank[xRoot] < rank[yRoot] {
73             root[xRoot] = yRoot
74         } else {
75             rank[xRoot] = root[xRoot] + 1
76             root[xRoot] = yRoot
77         }
78     }
79 }

64ms

 1 class Solution {
 2     func equationsPossible(_ equations: [String]) -> Bool {
 3         var dict: [Character: Set<Character>] = [:]
 4         var val = 0
 5         
 6         var res = true
 7         
 8         for equation in equations {
 9             var equation = equation
10             
11             let charA = equation.removeFirst()
12             let sym = equation.removeFirst()
13             if sym != "=" {continue}
14             
15             equation.removeFirst()
16             let charB = equation.removeFirst()
17             
18             if dict[charA] == nil {
19                 dict[charA] = [charA]
20             }
21             
22             if dict[charB] == nil {
23                 dict[charB] = [charB]
24             }
25             
26             let unionSet = (dict[charA]!).union(dict[charB]!)
27             
28             for (char, _) in dict where unionSet.contains(char) {
29                 dict[char] = unionSet
30             }
31         }
32         
33         for equation in equations {
34             var equation = equation
35             
36             let charA = equation.removeFirst()
37             let sym = equation.removeFirst()
38             if sym != "!" {continue}
39             
40             equation.removeFirst()
41             let charB = equation.removeFirst()
42             
43             if charA == charB || (dict[charA] != nil && dict[charB] != nil && dict[charA] == dict[charB] ) {
44                 res = false
45                 break
46             }
47         }
48         
49         return res
50     }
51 }

76ms
 1 class Solution {
 2     func equationsPossible(_ equations: [String]) -> Bool {
 3         let unionFind = UnionFind.init(26)
 4         let startingValue = Character("a").ascii!
 5         for item in equations {
 6             if item[1] == "=" {
 7                 let left = Int(item.ascii[0] - startingValue)
 8                 let right = Int(item.ascii[3] - startingValue)
 9                 unionFind.union(left, right)
10             }
11         }
12 
13         for item in equations {
14             if item[1] == "!" {
15                 let left = Int(item.ascii[0] - startingValue)
16                 let right = Int(item.ascii[3] - startingValue)
17                 if unionFind.find(left) == unionFind.find(right) {
18                     return false
19                 }
20             }
21         }
22         return true
23     }
24 }
25 
26 public extension String {
27     subscript (i: Int) -> Character {
28         return self[index(startIndex, offsetBy: i)]
29     }
30 }
31 
32 public extension StringProtocol {
33     var ascii: [UInt32] {
34         return compactMap { $0.ascii }
35     }
36 }
37 
38 extension Character {
39     var isAscii: Bool {
40         return unicodeScalars.first?.isASCII == true
41     }
42     var ascii: UInt32? {
43         return isAscii ? unicodeScalars.first?.value : nil
44     }
45 }
46 
47 class UnionFind {
48     var root = [Int]()
49     var rank = [Int]()
50     
51     public init(_ n: Int) {
52         // if root is not initialized, 'self' captured by a closure before all members were initialized
53         (0...n-1).forEach { root.append($0) }
54         rank = [Int](repeating: 1, count: n)
55     }
56     
57     fileprivate func find(_ current: Int) -> Int {
58         var path = [Int]()
59         var current = current
60         while root[current] != current {
61             path.append(current)
62             current = root[current]
63         }
64         
65         for p in path {
66             root[p] = current
67         }
68         return current
69     }
70     
71     public func union(_ x: Int, _ y: Int) {
72         let xRoot = find(x)
73         let yRoot = find(y)
74         
75         if xRoot == yRoot {
76             return
77         }
78         if rank[xRoot] > rank[yRoot] {
79             root[yRoot] = xRoot
80         } else if rank[xRoot] < rank[yRoot] {
81             root[xRoot] = yRoot
82         } else {
83             rank[xRoot] = root[xRoot] + 1
84             root[xRoot] = yRoot
85         }
86     }
87 }

 

posted @ 2019-02-11 13:13  为敢技术  阅读(300)  评论(0编辑  收藏  举报