Kotlin實現LeetCode算法題之String to Integer (atoi)

 

題目String to Integer (atoi)(難度Medium)
git

大意是找出給定字串開頭部分的整型數值,忽略開頭的空格,注意符號,對超出Integer的數作取邊界值處理。算法

 

方案1測試

 1 class Solution {
 2     fun myAtoi(str: String): Int {
 3         val maxInt = "2147483647"
 4         val maxIntS = "+2147483647"
 5         val minIntS = "-2147483648"
 6         val lengthMI = maxInt.length
 7         val lengthMIS = maxIntS.length
 8         var result = ""
 9         var strR = str.trim()
10 
11         //strR爲空
12         if (strR.isEmpty()) {
13             return 0
14         }
15 
16         //strR不爲空,且不以+/-開頭
17         if ('+' != strR[0] && '-' != strR[0]) {
18             //不以數字開頭
19             if (!strR[0].isDigit()) {
20                 return 0
21             }
22 
23             //以數字開頭
24             for (c in strR) {
25                 if (c.isDigit()) {
26                     result += c
27                 } else {
28                     break
29                 }
30             }
31             if (result.length > lengthMI ||
32                     (result.length == lengthMI && result > maxInt)) {
33                 result = maxInt
34             }
35             return result.toInt()
36         }
37 
38         //strR以+/-開頭
39         //後不是跟數字
40         if (strR.length == 1 || (strR.length > 1 && !strR[1].isDigit())) {
41             return 0
42         }
43 
44         //後跟數字
45         result += strR[0]
46         for (c in strR.subSequence(1, strR.length)) {
47             if (c.isDigit()) {
48                 result += c
49             } else {
50                 break
51             }
52         }
53         if (result[0] == '+' && (result.length > lengthMIS ||
54                 (result.length == lengthMIS && result > maxIntS))) {
55             result = maxIntS
56         } else if (result[0] == '-' && (result.length > lengthMIS ||
57                 (result.length == lengthMIS && result > minIntS))) {
58             result = minIntS
59         }
60         return result.toInt()
61     }
62 }

將數字及其長度這種常量抽象出來,不至於代碼中充斥着一丟重複的數字和長度計算,爭取在平時的編碼過程當中養成好習慣。編碼

說到習慣,代碼中還有一點提一下,在對字串進行符號存在性、符號後字符等多種狀況的判斷時並無使用一長串的if..else..,而是每一個小分支直接用return終止。這樣的好處是代碼可讀性與可維護性強,編碼過程當中不會因分支過多而可能搞混或出現漏處理的狀況。spa

代碼先用trim()將字串開頭的空字符去除(若是存在的話),而後對有/無符號、是否緊跟數字等多種狀況作了清晰的判斷和相應的處理。code

 

LeetCode提交詳情blog

 從上圖看,總共測試了1047個數據,耗時582ms。ip

 

測試代碼:leetcode

1 fun main(args: Array<String>) {
2     val start = System.currentTimeMillis()
3     println(Solution().myAtoi("-0000000000000000006666666bb6aa"))
4     val end = System.currentTimeMillis()
5     println(end - start)
6 }

 

測試數據rem

這篇文章先不看算法的耗時,重點關注用於測試的數據。

根據題目的描述,給定字串中應該是能夠包含任意字符的,須要咱們用代碼進行處理,輸出要求的結果。

那麼,來看幾組測試字串及其輸出結果:

"   +0aa",0,返回正確的數值0

"   +066bb6aa",66

"   -06 6bb6aa",-6

"   -06666666666666666666bb6aa",-2147483648,數值向下越界

"06666666666666666666bb6aa",2147483647,數值向上越界

"0000000000000000006666666bb6aa",2147483647,???錯誤的結果,應該是6666666

"a0000000066bb6aa",0,不以符號或數字開頭,直接返回0

"- 0000000066bb6aa",0,符號後跟的不是數字,直接返回0

 

結果分析

能夠看到,除了打問號的那一組測試案例,其餘均獲得了符號要求的結果。即對於不知足要求的字串直接返回0,字串開頭的空字符不該影響結果,獲取數據過程當中遇到非數字立馬終止等。

因爲題目的描述中並無具體指明測試字串會是什麼樣,也沒有針對開頭不少0的狀況進行說明,雖然提交後是accepted狀態,但爲了算法的嚴謹性,仍是須要對上面出錯的狀況作進一步的處理。

 

方案2

 1 class Solution {
 2     fun myAtoi(str: String): Int {
 3         val maxInt = "2147483647"
 4         val maxIntS = "+2147483647"
 5         val minIntS = "-2147483648"
 6         val lengthMI = maxInt.length
 7         val lengthMIS = maxIntS.length
 8         var result = ""
 9         var strR = str.trim()
10 
11         //strR爲空
12         if (strR.isEmpty()) {
13             return 0
14         }
15 
16         //strR不爲空,且不以+/-開頭
17         if ('+' != strR[0] && '-' != strR[0]) {
18             //不以數字開頭
19             if (!strR[0].isDigit()) {
20                 return 0
21             }
22 
23             //以數字開頭
24             for (c in strR) {
25                 if (c.isDigit()) {
26                     result += c
27                 } else {
28                     break
29                 }
30             }
31             while (result.length > 1 && result[0] == '0') {
32                 result = result.removeRange(0, 1)
33             }
34             if (result.length > lengthMI ||
35                     (result.length == lengthMI && result > maxInt)) {
36                 result = maxInt
37             }
38             return result.toInt()
39         }
40 
41         //strR以+/-開頭
42         //後不是跟數字
43         if (strR.length == 1 || (strR.length > 1 && !strR[1].isDigit())) {
44             return 0
45         }
46 
47         //後跟數字
48         result += strR[0]
49         for (c in strR.subSequence(1, strR.length)) {
50             if (c.isDigit()) {
51                 result += c
52             } else {
53                 break
54             }
55         }
56         while (result.length > 2 && result[1] == '0') {
57             result = result.removeRange(1, 2)
58         }
59         if (result[0] == '+' && (result.length > lengthMIS ||
60                 (result.length == lengthMIS && result > maxIntS))) {
61             result = maxIntS
62         } else if (result[0] == '-' && (result.length > lengthMIS ||
63                 (result.length == lengthMIS && result > minIntS))) {
64             result = minIntS
65         }
66         return result.toInt()
67     }
68 }

 代碼第31-33及56-58行,其實就是針對數據開頭的0進行了移除(固然數據只有一個數字且爲0是要保留的),由於開頭0的存在不會影響數據的大小,反而會干擾字串的長度計算。測試結果:

"-0000000000000000006666666bb6aa",-6666666

相關文章
相關標籤/搜索