1. 程式人生 > >Kotlin實現LeetCode算法題之String to Integer (atoi)

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

測試案例 width 說明 max 根據 art system ise tar

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

技術分享

大意是找出給定字串開頭部分的整型數值,忽略開頭的空格,註意符號,對超出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終止。這樣的好處是代碼可讀性與可維護性強,編碼過程中不會因分支過多而可能搞混或出現漏處理的情況。

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

LeetCode提交詳情

技術分享

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

測試代碼:

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 }

測試數據

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

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

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

" +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

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