Problem Statement
Given n points on a 2D plane, find the maximum number of points that lie on the same straight line.
Original LeetCode problem page
My Solution in Swift
The basic idea is to calculate gradient of every pair of points, and group points with same gradient. The final answer is then the size of the largest group. This results in an O(n2) algorithm. However, we could do it in a smarter way. When we have considered all possible pairs involving a given point, we don’t have to consider that point again. Also, when the current largest group size is x, we don’t have to consider the rest points.count – x number of points anymore. Although this improves the best case to O(n), on average, the algorithm is still in O(n2).
With proper implementation (pre-specify Dictionary capacity and keep the capacity when resetting), my Swift code runs pretty fast. It is actually faster than my friend’s C++ implementation compiling with -Ofast optimisation flag.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
func maxPoints(points: [(Int, Int)]) -> Int { var lines: [Double:Int] = Dictionary(minimumCapacity: points.count) var maxNum = 0 for var i = 0; i < points.count - maxNum; ++i { var curMaxNum = 1 var sameCount = 0 for var j = i + 1; j < points.count; ++j { let (x1, y1) = points[i] let (x2, y2) = points[j] if x1 == x2 && y1 == y2 { sameCount++ } else { let slope: Double = x2 == x1 ? Double.infinity : Double(y2 - y1) / Double(x2 - x1) var line: Int! = lines[slope] if line != nil { lines[slope] = ++line! } else { line = 2 lines[slope] = line } curMaxNum = max(line, curMaxNum) } } maxNum = max(maxNum, curMaxNum + sameCount) lines.removeAll(keepCapacity: true) } return maxNum } |
Try It Yourself
1: each links to a blog post of mine that is dedicated to the problem
2: total execution time of a solution on my MacBook Pro (Late 2013, 2.6 GHz Intel Core i7, 16 GB 1600 MHz DDR3). Each solution is compiled with following command:
$ swiftc -O -sdk `xcrun --show-sdk-path --sdk macosx` json.swift main.swift -o mySolution
The total execution time is the average of 10 runs.
3: these test cases are semi-automatically :P retrieved from LeetCode Online Judge system and are kept in JSON format
4: each Xcode project includes everything (my Swift solution to a problem, its JSON test cases and a driver code to test the solution on those test cases)
Problem1 | Time2 | Test Cases3 | My Xcode Project4 |
Max Points on a Line | 3.648ms |
It’s not true that this programs’ speed is faster than my C++ code. My C++ can reach 1-2ms. when my hashing is randomly distributed. Guan tweaked his hashing size parameter to reach 3.648ms, his original speed was only 12ms. Also I used unordered_map in C++. Which is not a very good C++ hashing library. If I manage to find a better C++ hashing library and also use intel compiler (other than just g++). I believe my C++ code speed can be stabely always under 1-2ms, maybe even 0.9 ms .
Also for some reason Mac seems to have some restrictions on C++ unordered_map hashing. On my ubuntu, I managed to have my C++ program’s best speed to be 1.9ms with just g++ -Ofast compilation.
At least on average, mine performs better than yours on your Ubuntu machine. On my machine, mine always performs better Yes, it is your hashtable problem, but a language without a solid hashtable built-in definitely cannot win the future
No. It’s not about average time performance, it’s about best time performance. Hash tables/libraries can be changed to achieve stable best time performance results. Not saying swift won’t be the future. But we still have to realistic in what advantages of a language has over another. Swift is good, but C++ is definitely faster (at the moment). That’s my point. :). Also you can’t fairly compete a language against swift on mac (when swift is designed for mac). It’s only fair to compete on the machine the language prefers. On my ubuntu my best time is 1.9ms, and my average time is still around about. 3.34ms, so that still beats 3.648ms
But other than that, I still have to give a big thumb up for swift. As it really has differentiated itself in terms of high speed performance for a high level programming language. And i will be getting into swift programming as well. (But C/C++ is still faster than swift, haha ) very interested in swift_v2 that’s coming up.
As we have discussed earlier, the better speed of C++ is because it doesn’t have an automatic garbage collector. If you add your own garbage collector mechanism to your C++ implementation, both Swift and C++ should perform equally well. Also, in general, a manually added garbage collection mechanism will not out perform an automatic garbage collector (I remembered that I read this somewhere over Internet)
That’s not true. Swift’s garbage collector is ARC (which is claimed to be not a true/good garbage collector, it’s only taking advantages of reference counting to know where to garbage collect / free up memory.). If you take swift’s garbage collector out. Or write a simple programming language that doesn’t use extensive garbage collect. C++ still out performs swift in speed (at the moment). There’s really not enough evidence indicating swift is as fast as C++. At the moment facts indicate lower level language such as Fortran, C, C++ still dominates higher level language Such as Java, Swift, C#, Scala and etc in speed.