2020年2月23日
- 字符串轉換整數 (中等題)
題目描述:
首先,該函數會根據需要丟棄無用的開頭空格字符,直到尋找到第一個非空格的字符爲止。
當我們尋找到的第一個非空字符爲正或者負號時,則將該符號與之後面儘可能多的連續數字組合起來,作爲該整數的正負號;假如第一個非空字符是數字,則直接將其與之後連續的數字字符組合起來,形成整數。 該字符串除了有效的整數部分之後也可能會存在多餘的字符,這些字符可以被忽略,它們對於函數不應該造成影響。
注意:假如該字符串中的第一個非空格字符不是一個有效整數字符、字符串爲空或字符串僅包含空白字符時,則你的函數不需要進行轉換。在任何情況下,若函數不能進行有效的轉換時,請返回 0。
說明:
假設我們的環境只能存儲 32 位大小的有符號整數,那麼其數值範圍爲 [−231, 231 − 1]。如果數值超過這個範圍,請返回 INT_MAX (2147483647) 或 INT_MIN (−2147483648) 。
示例 1:
輸入: “42”
輸出: 42
示例 2:
輸入: " -42"
輸出: -42
解釋: 第一個非空白字符爲 ‘-’, 它是一個負號。我們儘可能將負號與後面所有連續出現的數字組合起來,最後得到 -42 。
示例 3:
輸入: “4193 with words”
輸出: 4193
解釋: 轉換截止於數字 ‘3’ ,因爲它的下一個字符不爲數字。
示例 4:
輸入: “words and 987”
輸出: 0
解釋: 第一個非空字符是 ‘w’, 但它不是數字或正、負號。因此無法執行有效的轉換。
示例 5:
輸入: “-91283472332”
輸出: -2147483648
解釋: 數字 “-91283472332” 超過 32 位有符號整數範圍。 因此返回-2147483648
方法代碼:
class Solution {
public int myAtoi(String str) {
if(str == "" || str == null || str.length() == 0) return 0;
int n = 0;
boolean temp1 = false;
boolean temp2 = false;
int start = 0;
//找到第一個非零字符
for (int i = 0; i < str.length(); i++){
if(str.charAt(i) == 32)
continue;
else{
start = i;
break;
}
}
//判斷符號
if(str.charAt(start) == 45 ){
temp1 = true;
start++;
}
else if(str.charAt(start) == 43 ){
temp1 = false;
start++;
}
逐個將字符轉成數字
for (int i = start; i < str.length(); i++) {
if((str.charAt(i) > 47 && str.charAt(i) < 58)) {
//判斷字符是否大於int類型的範圍
if(temp1 && (n*-1 <Integer.MIN_VALUE/10 || (str.charAt(i) > 56 && n*-1 ==Integer.MIN_VALUE/10)))
return -2147483648;
else if(!temp1 &&( n >Integer.MAX_VALUE/10 || (str.charAt(i) > 55 && n ==Integer.MAX_VALUE/10)))
return 2147483647;
else
n = n*10 + str.charAt(i) - 48;
}
else {
temp2 = true;
break;
}
}
if(temp2 && n == 0)
return 0;
else if(temp1)
return n *= -1;
else
return n;
}
}
方法解析:
首先要找到第一個非空字符,之後判斷正負符號,然後就開始將字符串格式轉化爲數字,在這期間需注意字符串轉換成的數字有沒有超過int類型的範圍,如果超過就返回int的最大或最小值,還要注意中間有沒有不是數字字符的字符,如果有就終止轉換。
2.迴文數(簡單題)
判斷一個整數是否是迴文數。迴文數是指正序(從左向右)和倒序(從右向左)讀都是一樣的整數。
示例 1:
輸入: 121
輸出: true
示例 2:
輸入: -121
輸出: false
解釋: 從左向右讀, 爲 -121 。 從右向左讀, 爲 121- 。因此它不是一個迴文數。
示例 3:
輸入: 10
輸出: false
解釋: 從右向左讀, 爲 01 。因此它不是一個迴文數。
方法代碼:
class Solution {
public boolean isPalindrome(int x) {
if(x < 0 || ( x % 10 == 0 && x != 0)) return false;
int n = 0;
int temp = x;
while(temp > n){
n = n*10 + temp% 10;
temp = temp / 10;
}
return n== temp || n/10 == temp;
}
}
方法解析:
將數字本身反轉,然後將反轉後的數字與原始數字進行比較,如果它們是相同的,那麼這個數字就是迴文。但是,如果反轉後的數字大於 int.MAX,我們將遇到整數溢出問題。按照第這個想法,爲了避免數字反轉可能導致的溢出問題,只考慮反轉數字的一半,畢竟,如果該數字是迴文,其後半部分反轉後應該與原始數字的前半部分相同。例如,輸入 1221,我們可以將數字 “1221” 的後半部分從 “21” 反轉爲 “12”,並將其與前半部分 “12” 進行比較,因爲二者相同,我們得知數字 1221 是迴文。
3.盛最多水的容器(中等題)
給定 n 個非負整數 a1,a2,…,an,每個數代表座標中的一個點 (i, ai) 。在座標內畫 n 條垂 直線,垂直線 i 的兩個端點分別爲 (i, ai) 和 (i, 0)。找出其中的兩條線,使得它們與 x 軸共同構成的容器可以容納最多的水。
說明:你不能傾斜容器,且 n 的值至少爲 2。
圖中垂直線代表輸入數組 [1,8,6,2,5,4,8,3,7]。在此情況下,容器能夠容納水(表示爲藍色部分)的最大值爲 49。
示例:
輸入: [1,8,6,2,5,4,8,3,7]
輸出: 49
方法代碼:
class Solution {
public int maxArea(int[] height) {
int max = 0;
int i = 0, j = height.length - 1 ;
int area = 0;
while(i < j){
area = height[i] < height[j] ?
Math.max(area, (j-i)*height[i++]):
Math.max(area, (j-i)*height[j--]);
}
return area;
}
}
方法解析:
算法流程: 設置雙指針 i,j分別位於容器壁兩端,根據規則移動指針(後續說明),並且更新面積最大值area,直到 i == j 時返回 area。
指針移動規則與證明: 每次選定圍成水槽兩板高度 h[i],h[j]中的短板,向中間收窄1格。以下證明:
設每一狀態下水槽面積爲 S(i, j),(0 <= i < j < n),由於水槽的實際高度由兩板中的短板決定,則可得面積公式 S(i, j) = min(h[i], h[j]) × (j - i)。
在每一個狀態下,無論長板或短板收窄11格,都會導致水槽底邊寬度 −1:
若向內移動短板,水槽的短板 min(h[i],h[j]) 可能變大,因此水槽面積 S(i, j)可能增大。
若向內移動長板,水槽的短板 min(h[i],h[j]) 不變或變小,下個水槽的面積一定小於當前水槽面積。
因此,向內收窄短板可以獲取面積最大值。換個角度理解:
若不指定移動規則,所有移動出現的 S(i, j)S(i,j) 的狀態數爲 C(n, 2),即暴力枚舉出所有狀態。
在狀態 S(i, j)下向內移動短板至S(i+1,j)(假設 h[i] < h[j]h[i]<h[j] ),則相當於消去了 {S(i, j - 1), S(i, j - 2), … , S(i, i + 1)}狀態集合。而所有消去狀態的面積一定 <= S(i, j)<=S(i,j):
短板高度:相比 S(i, j)相同或更短(<= h[i]);
底邊寬度:相比 S(i, j)更短。
因此所有消去的狀態的面積都 < S(i, j)<S(i,j)。通俗的講,我們每次向內移動短板,所有的消去狀態都不會導致丟失面積最大值 。
- 整數轉羅馬數字(中等題)
羅馬數字包含以下七種字符: I, V, X, L,C,D 和 M。
字符 數值
I 1
V 5
X 10
L 50
C 100
D 500
M 1000
例如, 羅馬數字 2 寫做 II ,即爲兩個並列的 1。12 寫做 XII ,即爲 X + II 。 27 寫做 XXVII, 即爲 XX + V + II 。
通常情況下,羅馬數字中小的數字在大的數字的右邊。但也存在特例,例如 4 不寫做 IIII,而是 IV。數字 1 在數字 5 的左邊,所表示的數等於大數 5 減小數 1 得到的數值 4 。同樣地,數字 9 表示爲 IX。這個特殊的規則只適用於以下六種情況:
I 可以放在 V (5) 和 X (10) 的左邊,來表示 4 和 9。
X 可以放在 L (50) 和 C (100) 的左邊,來表示 40 和 90。
C 可以放在 D (500) 和 M (1000) 的左邊,來表示 400 和 900。
給定一個整數,將其轉爲羅馬數字。輸入確保在 1 到 3999 的範圍內。
示例 1:
輸入: 3
輸出: “III”
示例 2:
輸入: 1994
輸出: “MCMXCIV”
解釋: M = 1000, CM = 900, XC = 90, IV = 4.
方法代碼:
class Solution {
public String intToRoman(int num) {
if(num<1 || num > 3999) return "";
StringBuilder str = new StringBuilder();
int[] num1 = {1000,900,500,400,100,90,50,40,10,9,5,4,1};
String[] l = {"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"};
int index = 0;
while(index < num1.length){
while(num >= num1[index]) {
str.append(l[index]);
num -= num1[index];
}
index++;
}
return str.toString();
}
}
方法解析:
在表示一個較大整數的時候,“羅馬數字”的設計者不會讓你都用 11 加起來,我們總是希望寫出來的“羅馬數字”的個數越少越好,以方便表示,並且這種表示方式還應該是唯一的。所以我們要從最大的位數開始轉換。
這道問題,類似於用最少的紙幣湊成一個整數,貪心算法的規則如下:
每一步都使用當前較大的羅馬數字作爲加法因子,最後得到羅馬數字表示就是長度最少的。
- 羅馬數字轉整數(簡單題)
羅馬數字包含以下七種字符: I, V, X, L,C,D 和 M。
字符 數值
I 1
V 5
X 10
L 50
C 100
D 500
M 1000
例如, 羅馬數字 2 寫做 II ,即爲兩個並列的 1。12 寫做 XII ,即爲 X + II 。 27 寫做 XXVII, 即爲 XX + V + II 。通常情況下,羅馬數字中小的數字在大的數字的右邊。但也存在特例,例如 4 不寫做 IIII,而是 IV。數字 1 在數字 5 的左邊,所表示的數等於大數 5 減小數 1 得到的數值 4 。同樣地,數字 9 表示爲 IX。這個特殊的規則只適用於以下六種情況:
I 可以放在 V (5) 和 X (10) 的左邊,來表示 4 和 9。
X 可以放在 L (50) 和 C (100) 的左邊,來表示 40 和 90。
C 可以放在 D (500) 和 M (1000) 的左邊,來表示 400 和 900。
給定一個羅馬數字,將其轉換成整數。輸入確保在 1 到 3999 的範圍內。
示例 1:
輸入: “III”
輸出: 3
示例 2:
輸入: “MCMXCIV”
輸出: 1994
解釋: M = 1000, CM = 900, XC = 90, IV = 4.
方法代碼:
class Solution {
public int romanToInt(String s) {
Map<Character, Integer> map = new HashMap<>();
map.put('I', 1);
map.put('V', 5);
map.put('X', 10);
map.put('L', 50);
map.put('C', 100);
map.put('D', 500);
map.put('M', 1000);
int n = 0;
char[] c = s.toCharArray();
for(int i = 0 ; i < c.length ; i++) {
int j = i+1;
if(j < c.length && map.get(c[i]) < map.get(c[j])) {
n = map.get(c[j]) + n - map.get(c[i]);
i++;
}
else
n += map.get(c[i]);
}
return n;
}
}
方法解析:首先將所有羅馬數字所代表的阿拉伯數字一次存儲在Map數組中,該方法最重要的是如果字符串中該字符所代表的值大於該字符後面的字符所代表的值,那麼就應該減去該字符的值,所以判斷每個字符的與後一個字符的關係,逐個加該符號的值或減去該符號的值。
6.最長公共前綴(簡單題)
編寫一個函數來查找字符串數組中的最長公共前綴。
如果不存在公共前綴,返回空字符串 “”。
示例 1:
輸入: [“flower”,“flow”,“flight”]
輸出: “fl”
示例 2:
輸入: [“dog”,“racecar”,“car”]
輸出: “”
解釋: 輸入不存在公共前綴。
方法代碼:
class Solution {
public String longestCommonPrefix(String[] strs) {
if(strs.length == 1) return strs[0];
if(strs.length == 0) return "";
String str = "";
char[] temp = strs[0].toCharArray();
for(int j = 0; j < temp.length ; j++) {
for(int i = 1 ; i < strs.length; i++) {
if(j >= strs[i].length() )
return str;
if(temp[j] != strs[i].charAt(j))
return str;
}
str += temp[j];
}
return str;
}
}
方法解析:該方法先將第一個字符串的每個字符逐個與剩下的字符串的相應位置的字符進行比較,如遇到不相等的立馬返回已得前綴字符串。