資料結構與演算法學習(二)-字串相關問題
技術標籤:java
我的個人部落格Alexios,歡迎大家來吐槽交流。
1、String、StringBuffer與StringBuilder的區別
1.1、String類
分析原始碼可知,String物件的內容是儲存在一個char陣列中,且這個陣列使用final修飾,這也是String物件不可變的原因。當進行字串拼接時,虛擬機器會新建一個字串物件,然後將新的字串物件賦值給原來的引用,而不是真的修改了原來字串物件的值。
字串重寫了Object父類的equals方法。
1.2、StringBuffer類和StringBuilder類
這兩個類均繼承於AbstractStringBuilder類,但分析原始碼可知StringBuffer的方法都添加了synchronized關鍵詞進行修飾,所以StringBuffer是執行緒安全的,而沒有使用synchronized修飾方法的StringBuilder是執行緒不安全的,但StringBuilder的速度要遠遠高於StringBuffer,所以在能保證執行緒安全的情況下,StringBuilder的優先順序要高於StringBuffer。
1.3、總結
- String是一個final修飾的類,所有的屬性也是final的,所以String具有不可變性,也就是對字串的操作,如拼接、剪下都會產生新的String物件。
- StringBuffer本質是一個執行緒安全的可修改字串序列。因為保證執行緒安全,所以會帶來額外的效能消耗。
- StringBuilder本質上和StringBuffer沒有區別,但是StringBuilder去掉了執行緒安全部分提高了操作效率,是絕大部分情況下字串拼接的首選。
- 如果確定拼接字串會發生多次,並且長度可預計,那麼可以在開始的時候指定合適的大小,避免陣列擴容造成的開銷。
2、找出字串中出現最多次的字元和出現的次數
遍歷字串,並使用一個HashMap來儲存出現字元及出現的次數,以字元為key,次數為value。解題思路如下
-
假定字串中出現最多的字元maxCode為當前字串的第一個元素,出現次數maxCount初始化為0
-
遍歷字串,判斷當前字元是否在hashmap的key中,如果包含,令次數+1,否則將該字元為key,1為value放入hashmap中
-
判斷maxCount和當前字元出現次數的關係,如果maxCount小於當前字元出現次數,就令maxCode = 當前字元,然後更新maxCode,最後返回maxCode和maxCount即可。
程式碼實現
/***
* 找出字串中出現最多次的字元和出現的次數
* @param str 目標字串
* @return 以maxCode為鍵、maxCount為值的map
*/
public static Map<Character, Integer> findMostCodeAndCount(String str) {
char maxCode = str.charAt(0);
int maxCount = 0;
Map<Character, Integer> map = new HashMap<>();
for (int i = 0; i < str.length(); i++) {
Character currentCode = str.charAt(i);
Integer count = map.get(currentCode);
if(count == null) {
count = 1;
} else {
count++;
}
map.put(currentCode, count);
if(maxCount < count) {
maxCode = currentCode;
maxCount = count;
}
}
Map<Character, Integer> result = new HashMap<>();
result.put(maxCode,maxCount);
return result;
}
測試程式碼及結果
String str = "abcacba";
Map result = findMostCodeAndCount(str);
System.out.println(result);
- 結果
3、找出字串中第一次重複出現的字元
使用一個HashSet來解決問題,由於Set有不允許元素重複的性質,Set的add方法在新增重複值是會返回false,所以我們可以用這個性質來判斷元素是否重複。
程式碼實現
/***
* 找出字串中第一次重複出現的字元
* @param str 目標字串
* @return 返回第一次重複的字元
*/
public static Character getFirstRepeat(String str) {
Set<Character> set = new HashSet<>();
Character result = null;
for (int i = 0; i < str.length(); i++) {
Character currentCode = str.charAt(i);
if(!set.add(currentCode)) {
result = currentCode;
break;
}
}
return result;
}
測試程式碼和結果
String str = "abcacba";
Character result = getFirstRepeat(str);
System.out.println(result);
- 結果
4、兩個大數之和
題目描述:現在有兩個數,位數均超過1000位,例如
String a = “123343432…”
String b = “3974928374928…”
這兩個大數無法轉換為Integer計算,所以我們使用兩個陣列來儲存這兩個數,然後進行計算。
解題思路如下
- 設這兩個數中大的數的位數位m,則結果的最大位數位m+1
- 用一個int陣列來儲存結果
程式碼實現
/***
* 程式設計兩個大數之和
* @param num1
* @param num2
* @return
*/
public static String sumOfBigNum(String num1,String num2) {
char[] largeArray = null;
char[] smallArray = null;
if(num1.length() >= num2.length()) {
largeArray = num1.toCharArray();
smallArray = num2.toCharArray();
} else {
largeArray = num2.toCharArray();
smallArray = num1.toCharArray();
}
int[] res = new int[largeArray.length + 1];
for (int i = 0; i < largeArray.length; i++) {
res[i] = largeArray[largeArray.length - i - 1] - '0';
}
for (int i = 0; i < smallArray.length; i++) {
res[i] += smallArray[smallArray.length - i - 1] - '0';
}
for (int i = 0; i < res.length - 1; i++) {
if(res[i] > 9) {
res[i + 1] += res[i] / 10;
res[i] %= 10;
}
}
StringBuilder stringBuilder = new StringBuilder();
for (int i = res.length - 1; i >= 0; i--) {
stringBuilder.append(res[i]);
}
String result = stringBuilder.toString();
if(result.startsWith("0")) {
result = result.substring(1);
}
return result;
}
測試程式碼和結果
String num1 = "12345";
String num2 = "56756";
Integer n1 = Integer.valueOf(num1);
Integer n2 = Integer.valueOf(num2);
Integer sum = n1 + n2;
System.out.println("計算機計算結果為:" + sum);
System.out.println("函式計算結果位:" + sumOfBigNum(num1,num2));
- 結果