目錄
9.longest-substring-without-repeating-characters
10.longest-palindromic-substring
1.length-of-last-word
題目:給出一個只包含大小寫字母和空格的字符串s,請返回字符串中最後一個單詞的長度,如果字符串中沒有最後一個單詞,則返回0。注意:單詞的定義是僅由非空格字符組成的字符序列。例如:s ="Hello World",返回5。
分析:先用String的trim()方法去掉前後的空格,反向遍歷進行計算倒數第一個單詞的長度即可。
public int lengthOfLastWord(String s) {
s = s.trim();
int count = 0;
for(int i = s.length() - 1;i >= 0;i--){
if(s.charAt(i) == ' ')
break;
count++;
}
return count;
}
2.add-binary
題目:給出兩個用字符串表示的二進制數,返回他們的和(也用字符串表示)。例如:a ="11",b ="1",返回"100".
分析:先在短的字符串前面填充0讓兩字符串長度相同,從後往前依次相加即可,二進制相加可以用異或進行計算,可提高計算效率。
public String addBinary(String a, String b) {
if(a.length() == 0 || b.length() == 0)
return a + b;
int len = Math.max(a.length(),b.length());
while(a.length() < len)
a = "0" + a;
while(b.length() < len)
b = "0" + b;
String result = "";
int flag = 0;
for(int i = len - 1;i >= 0;i--){
int m = a.charAt(i) - '0',n = b.charAt(i) - '0';
result = (m ^ n ^ flag) + result;
if(m + n + flag < 2)
flag = 0;
else
flag = 1;
}
if(flag == 1)
result = 1 + result;
return result;
}
3.multiply-strings
題目:給出兩個用字符串表示的數字,將兩個數字的乘積作爲字符串返回。備註:數字可以無限大,且是非負數。
分析:分治法。先舉個簡單的例子來說,比如99 * 33實際上會等於90 * 33 + 9 * 33,也就是把99從中間拆分,分別乘以33.所以我們可以將大數相乘a和b中的其中一個數從中間進行拆分,假設我們將a前後拆成a1、a2,那麼就將問題拆成了a1*b,a2*b,最後結果就是a1*b後面添加a2.length個0與a2*b的和,問題又轉化成了大數相加的問題。對於大數相加問題,可以將兩個數字的後八位分離出來進行相加,再與數字其它位數的和進行拼湊,注意拼湊時有可能後8位數字相加之後的長度小於8,這時我們要進行補0,有可能長度大於9,也就是最高位爲1時,這時我們要將高位數之和加上1,再與剩下8位進行拼湊。Integer.MAX_VALUE爲2147483647,所以當兩個數的長度均小於等於4時才進行直接相乘,長度小於等於8時才進行直接相加,以防止溢出。
public String multiply(String num1, String num2) {
int len1 = num1.length(),len2 = num2.length();
if(len1 <= 4 && len2 <= 4)//遞歸出口
return Integer.parseInt(num1) * Integer.parseInt(num2) + "";
if(len1 > 4){//將長度大於4的字符串從中間進行拆分
int mid = len1 >> 1;
String s1 = num1.substring(0,mid);
String s2 = num1.substring(mid);
return add(multiply(s1,num2) + zero(s2.length()),multiply(s2,num2));
}
return multiply(num2,num1);
}
private String add(String num1, String num2) {//大數相加
int len1 = num1.length(),len2 = num2.length();
if(len1 <= 8 && len2 <= 8)//遞歸出口
return Integer.parseInt(num1) + Integer.parseInt(num2) + "";
String a1 = "0",a2 = num1;
if(len1 > 8) {//分離出num1後8位
a1 = num1.substring(0,len1 - 8);
a2 = num1.substring(len1 - 8);
}
String b1 = "0",b2 = num2;
if(len2 > 8) {//分離出num2後8位
b1 = num2.substring(0,len2 - 8);
b2 = num2.substring(len2 - 8);
}
String result = add(a2,b2);
if(result.length() > 8)
return add(add(a1,b1),"1") + result.substring(1);
else
return add(a1,b1) + zero(8 - result.length()) + result;
}
private String zero(int n){//返回n個0的字符串
if(n == 0) return "";
if(n == 1) return "0";
String s = zero(n / 2);
return s + s + zero(n % 2);
}
4.valid-number
題目:判斷給出的字符串是否是數字。一些例子:"0"=>true;" 0.1 "=>true;"abc"=>false;"1 a"=>false;"2e10"=>true
分析:見劍指offer面試題20 https://blog.csdn.net/Nibaby9/article/details/103822794
5.string-to-integer-atoi
題目:實現函數 atoi 。函數的功能爲將字符串轉化爲整數。提示:仔細思考所有可能的輸入情況。這個問題故意描述的很模糊(沒有給出輸入的限制),你需要自己考慮所有可能的情況。
分析:見劍指offer面試題67 https://blog.csdn.net/Nibaby9/article/details/103822794
6.roman-to-integer
題目:請將給出的羅馬數字轉化爲整數,保證輸入的數字範圍在1 到 3999之間。
分析:羅馬數字轉換規則:I --> 1、V --> 5、X --> 10、L --> 50、C --> 100、D --> 500、M --> 1000,單個符號重複多少次,就表示多少倍。最多重複3次,比如:CCC表示300 XX表示20,但150並不用LLL表示,這個規則僅適用於I X C M;如果相鄰級別的大單位在右,小單位在左,表示大單位中扣除小單位,比如:IX表示9 IV表示4 XL表示40。這裏用暴力破解法,IV:4 IX:9 XL:40 XC:90 CD:400 CM:900這種組合實際上在羅馬數中只會出現一次,所以可以遇到這種組合可以在計算的和中減去多加的數,比如說IV如果用I+V的值就爲6,只要再減去2即可。
public int romanToInt(String s) {
int sum = 0;
for(int i = 0;i < s.length();i++) {
char c = s.charAt(i);
if(c == 'I') sum+=1;
if(c == 'V') sum+=5;
if(c == 'X') sum+=10;
if(c == 'L') sum+=50;
if(c == 'C') sum+=100;
if(c == 'D') sum+=500;
if(c == 'M') sum+=1000;
}
if(s.contains("IV") || s.contains("IX"))//4、9
sum -= 2;
if(s.contains("XL") || s.contains("XC"))// 40、90
sum -= 20;
if(s.contains("CD") || s.contains("CM"))// 400、900
sum -= 200;
return sum;
}
7.integer-to-roman
題目:請將給出的整數轉化爲羅馬數字,保證輸入數字的範圍在1 到 3999之間。
分析:利用窮舉法,將各位數分別轉換爲羅馬數字即可。
public String intToRoman(int num) {
String[] one = {"","I","II","III","IV","V","VI","VII","VIII","IX"};
String[] two = {"","X","XX","XXX","XL","L","LX","LXX","LXXX","XC"};
String[] three = {"","C","CC","CCC","CD","D","DC","DCC","DCCC","CM"};
String[] four = {"","M","MM","MMM"};
String result = "";
result += four[num / 1000];
result += three[num % 1000 / 100];
result += two[num % 100 / 10];
result += one[num % 10];
return result;
}
8.longest-common-prefix
題目:編寫一個函數來查找字符串數組中的最長公共前綴。如果不存在公共前綴,返回空字符串 ""
。假設所有輸入只包含小寫字母 a-z
。
分析:依次遍歷字符串,當遍歷到第 i個字符串時,找到最長公共前綴,當公共前綴爲“”時,可直接返回答案爲空字符串,否則遍歷完字符串數組後可以得到。
public String longestCommonPrefix(String[] strs) {
if (strs.length == 0)
return "";
String prefix = strs[0];
for (int i = 1; i < strs.length; i++) {
while (strs[i].indexOf(prefix) != 0) {//如果不爲0,說明prefix不是str[i]的前綴
prefix = prefix.substring(0, prefix.length() - 1);
if (prefix.length() == 0)
return "";
}
}
return prefix;
}
9.longest-substring-without-repeating-characters
題目:給定一個字符串,找出最長的不具有重複字符的子串的長度。例如,“abcabcbb”不具有重複字符的最長子串是“abc”,長度爲3。對於“bbbbb”,最長的不具有重複字符的子串是“b”,長度爲1。
分析:見劍指offer面試題48 https://blog.csdn.net/Nibaby9/article/details/10382279
10.longest-palindromic-substring
題目:找出給出的字符串S中最長的迴文子串。假設S的最大長度爲1000,並且只存在唯一解。
分析:動態規劃。定義一個函數f(i,j)表示字符串第i個位置到第j個位置是否爲迴文串,從左到右依次掃描字符將其作爲子串的結束位置,讓子串往前進行延伸,在計算f(i,j)時就可保證f(i+1,j-1)已計算出,那麼f(i,j) = (s.charAt(i) == s.charAt(j) && f(i+1,j-1))。
public String longestPalindrome(String s) {
if(s.length() == 0)
return s;
int max = 1;
int start = 0;//保存最長迴文子串的起始點
boolean [][]dp = new boolean[s.length()][s.length()];//子串s[i..j] 是否是迴文子串
for(int i = 0;i < s.length();i++)
dp[i][i] = true;
for(int j = 1;j < s.length();j++){//子串結束位置
for(int i = j-1;i >= 0;i--){//子串開始位置
if(j - i < 2)
dp[i][j] = s.charAt(i) == s.charAt(j);
else
dp[i][j] = (s.charAt(i) == s.charAt(j) && dp[i+1][j-1]);
if(dp[i][j] && j-i+1 > max){
max = j - i + 1;
start = i;
}
}
}
return s.substring(start,start + max);
}