LeetCode 刷題記錄(8,9,10)—Java語言
8. 字串轉整數 (atoi)
題目
實現 atoi,將字串轉為整數。
在找到第一個非空字元之前,需要移除掉字串中的空格字元。如果第一個非空字元是正號或負號,選取該符號,並將其與後面儘可能多的連續的數字組合起來,這部分字元即為整數的值。如果第一個非空字元是數字,則直接將其與之後連續的數字字元組合起來,形成整數。
字串可以在形成整數的字元後面包括多餘的字元,這些字元可以被忽略,它們對於函式沒有影響。
當字串中的第一個非空字元序列不是個有效的整數;或字串為空;或字串僅包含空白字元時,則不進行轉換。
若函式不能執行有效的轉換,返回 0。
說明:
假設我們的環境只能儲存 32 位有符號整數,其數值範圍是 [−231, 231 − 1]。如果數值超過可表示的範圍,則返回 INT_MAX (231 − 1) 或 INT_MIN (−231) 。
示例 1:
輸入: “42”
輸出: 42
示例 2:
輸入: ” -42”
輸出: -42
解釋: 第一個非空白字元為 ‘-‘, 它是一個負號。
我們儘可能將負號與後面所有連續出現的數字組合起來,最後得到 -42 。
示例 3:
輸入: “4193 with words”
輸出: 4193
解釋: 轉換截止於數字 ‘3’ ,因為它的下一個字元不為數字。
示例 4:
輸入: “words and 987”
輸出: 0
解釋: 第一個非空字元是 ‘w’, 但它不是數字或正、負號。
因此無法執行有效的轉換。
示例 5:
輸入: “-91283472332”
輸出: -2147483648
解釋: 數字 “-91283472332” 超過 32 位有符號整數範圍。
因此返回 INT_MIN (−231) 。
思路
這個題目即需要自己實現一個字串解析整數的功能方法,根據以上示例可以得出三個結論
- 在沒有遇到數字或正負號之前,只能出現空格否則不能轉換。
- 遇到數字或者正負號之後在遇見空格或者其他字元(包括正負號)轉換停止之後的數字不在轉換。
- 轉化的值可能會超出int範圍,一旦轉化的當前整數值超出int範圍,停止轉化。
知道這些特徵之後就很好解決問題了,直接通過迴圈判斷對應的條件然後做出相應的操作即可
程式碼
其中flag表示是否出現過數字或者正負號。未出現之前,只能接受空格字元,當出現過之後只能接受數字字元。不符合的條件一成立則停止轉化,輸出結果,最後做防止溢位轉化。
class Solution {
public int myAtoi(String str) {
boolean flag = false;
boolean posi = true;
long res = 0;
for(int i=0;i<str.length();i++){
char c = str.charAt(i);
if(c>='0'&&c<='9')
res = res*10+(c-'0');
else if(c=='-'&&!flag)
posi = false;
else if(c=='+'&&!flag)
posi = true;
else if(flag||!flag&&c!=' ')
break;
if(!flag&&c!=' ')
flag = true;
if(res-1>Integer.MAX_VALUE)
break;
}
return posi?(int)Math.min(res,Integer.MAX_VALUE)
:(int)Math.max(-1*res,Integer.MIN_VALUE);
}
}
9. 迴文數
題目
判斷一個整數是否是迴文數。迴文數是指正序(從左向右)和倒序(從右向左)讀都是一樣的整數。
示例 1:
輸入: 121
輸出: true
示例 2:
輸入: -121
輸出: false
解釋: 從左向右讀, 為 -121 。 從右向左讀, 為 121- 。因此它不是一個迴文數。
示例 3:
輸入: 10
輸出: false
解釋: 從右向左讀, 為 01 。因此它不是一個迴文數。
思路
這個題目比較簡單,首先明確一點負數因為含有’-‘所以絕對不是迴文數。0是迴文數。然後對整數逐位反轉。組成一個新數,比較是否一致即可。
程式碼
class Solution {
public boolean isPalindrome(int x) {
if(x==0)
return true;
else if(x<0)
return false;
int temp = x;
int contrast = 0;
while(temp>0){
contrast = contrast*10+temp%10;
temp/=10;
}
return contrast==x;
}
}
10. 正則表示式匹配
題目
給定一個字串 (s) 和一個字元模式 (p)。實現支援 ‘.’ 和 ‘*’ 的正則表示式匹配。
‘.’ 匹配任意單個字元。
‘*’ 匹配零個或多個前面的元素。
匹配應該覆蓋整個字串 (s) ,而不是部分字串。
說明:
s 可能為空,且只包含從 a-z 的小寫字母。
p 可能為空,且只包含從 a-z 的小寫字母,以及字元 . 和 *。
示例 1:
輸入:
s = “aa”
p = “a”
輸出: false
解釋: “a” 無法匹配 “aa” 整個字串。
示例 2:
輸入:
s = “aa”
p = “a*”
輸出: true
解釋: ‘*’ 代表可匹配零個或多個前面的元素, 即可以匹配 ‘a’ 。因此, 重複 ‘a’ 一次, 字串可變為 “aa”。
示例 3:
輸入:
s = “ab”
p = “.*”
輸出: true
解釋: “.” 表示可匹配零個或多個(‘‘)任意字元(‘.’)。
示例 4:
輸入:
s = “aab”
p = “c*a*b”
輸出: true
解釋: ‘c’ 可以不被重複, ‘a’ 可以被重複一次。因此可以匹配字串 “aab”。
示例 5:
輸入:
s = “mississippi”
p = “mis*is*p*.”
輸出: false
思路。
題目的要求是實現一個正則表示式的部分功能,首先並且一下’.’和’ * ‘的功能。’.’是匹配任意一個字元。’ * ‘是匹配前面一個元素零個或多個組成的字串。比如a*,可以表示”“、a、aa、aaa、aaaa……,之前就是這個地方沒有看清楚,糾結了很久。
那麼知道這些條件之後就能開始來判斷了。首先’.’和’ * ‘這兩者前者更容易匹配判斷,因為只要判斷其存在則兩串繼續往下判斷即可,後者匹配更復雜。有多種情景,當判斷的當前字元的下一個字元為’ * ‘時,首先判斷當前字元是否相等,如果不相等,即’ * ‘失去作用。則把p串的位置向後移動兩位(當前位判斷失敗,’ * ‘字元失去作用,直接匹配其後的字元)。
如果當前的字元匹配成功,那麼也有三種情況,第一種直接將p串向後移2位,這樣的話相當於忽略當前判斷成功結果,直接比較之後的字元是否與當前s串位置上的字元是否相等。(這樣做是為了避免一些特定情況的出現,即pa,p*pa,這種情況,當p 被略後才能正確的匹配成功)。第二種 即當匹配0個當前字元,將s串後移一位,p串後移兩位,直接與下面的字元進行匹配。第三種 即匹配多個當前字元。因為採取遞迴。直接將s串後移一位,繼續與p串當前字元進行判斷。如果當前字元的下一個字元不為’ * ‘時,判斷當前字元是否相等相等兩串後移繼續判斷,否則返回false。因為下一個不為’ * ‘,噹噹前字串的第一個和模式串中的第一不想匹配直接返回false即可(切不可將匹配當做尋找子串,兩者完全不同)。
class Solution {
public boolean isMatch(String s, String p) {
if(s==null||p==null)
return false;
return match(s,0,p,0);
}
private boolean match(String s,int sIndex,String p,int pIndex){
if(sIndex==s.length()&&pIndex==p.length())
return true;
else if(sIndex!=s.length()&&pIndex==p.length())
return false;
if(pIndex + 1<p.length() && p.charAt(pIndex+1)=='*'){
if(sIndex != s.length()&&p.charAt(pIndex)==s.charAt(sIndex)
||p.charAt(pIndex) == '.' && sIndex !=s.length())
return match(s,sIndex,p,pIndex+2)
||match(s,sIndex+1,p,pIndex+2)
||match(s,sIndex+1,p,pIndex);
else
return match(s,sIndex,p,pIndex+2);
}else if(sIndex!=s.length()&&(p.charAt(pIndex)
==s.charAt(sIndex)||p.charAt(pIndex)=='.'))
return match(s,sIndex+1,p,pIndex+1);
return false;
}
}