forked from soapyigu/LeetCode-Swift
-
Notifications
You must be signed in to change notification settings - Fork 0
/
FindClosestPalindrome.swift
69 lines (56 loc) · 2.16 KB
/
FindClosestPalindrome.swift
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
/**
* Question Link: https://leetcode.com/problems/find-the-closest-palindrome/
* Primary idea: Five possible cases -- the numbers with digits less or greater than current number;
* the numbers with same digits' number but replication of the mutation
* (+1 or -1 if the original number itself is palindrome) of the first half.
*
* Time Complexity: O(n), Space Complexity: O(1)
*
*/
class FindClosestPalindrome {
func nearestPalindromic(_ n: String) -> String {
let chars = Array(n)
var candidates = Set<String>()
candidates.insert(buildLeftNum(n))
candidates.insert(buildRightNum(n))
for distance in -1...1 {
candidates.insert(buildPalindromeOnMiddle(chars, distance))
}
return findNearest(n, candidates)
}
private func buildLeftNum(_ num: String) -> String {
return String(repeating: "9", count: num.count - 1)
}
private func buildRightNum(_ num: String) -> String {
return "1" + String(repeating: "0", count: num.count - 1) + "1"
}
private func buildPalindromeOnMiddle(_ n: [Character], _ distance: Int) -> String {
let middleIdx = n.count % 2 == 0 ? n.count / 2 - 1: n.count / 2
let leftPart = String(Int(String(n[0...middleIdx]))! + distance)
if n.count % 2 != 0 {
return String(leftPart.dropLast() + leftPart.reversed())
} else {
return String(leftPart + leftPart.reversed())
}
}
private func findNearest(_ n: String, _ candidates: Set<String>) -> String {
guard let num = Int(n) else {
fatalError("Invalid Input")
}
var nearest = 0
for candidate in candidates {
guard let cNum = Int(candidate) else {
continue
}
if cNum == num {
continue
}
if abs(cNum - num) < abs(nearest - num) {
nearest = cNum
} else if abs(cNum - num) == abs(nearest - num) {
nearest = min(cNum, nearest)
}
}
return String(nearest)
}
}