力扣389-找不同(Java詳細題解,位運算100%)
力扣389-找不同
一、原題題目
1.1 題目
給定兩個字串 s 和 t,它們只包含小寫字母。字串 t 由字串 s 隨機重排,然後在隨機位置新增一個字母。請找出在 t 中被新增的字母。
1.2 示例
-
示例一
輸入: s = “abcd”, t = “abcde”
輸出: “e”
解釋: ‘e’ 是那個被新增的字母。
-
示例二
輸入: s = “”, t = “y”
輸出: “y”
-
示例三
輸入: s = “a”, t = “aa”
輸出: “a”
-
示例四
輸入: s = “ae”, t = “aea”
輸出: “a”
提示:
0 <= s.length <= 1000
t.length == s.length + 1
s
和t
只包含小寫字母
來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/find-the-difference/
二、解題思路1
2.1 題目理解分析
題目很直白,也非常容易想到思路,我第一個思路就是用一個 HashMap 去儲存 s 字串中每個字元的個數(字元作為 key ,個數作為 value)。然後遍歷 t 字串的時候去減掉對應字元的個數值,當有不在 HashMap 中的字元或個數已經為0的字元即為加進去的字元。
2.2 詳細程式碼(Java)
public class Solution {
public char findTheDifference(String s, String t) {
HashMap<Character,Integer> map = new HashMap<>(); // 定義 map
for (int i = 0;i<s.length();i++){ // 統計 s 中的每個字元個數
char ch = s.charAt(i);
map.put(ch,map.containsKey(ch)?map.get (ch)+1:1);
}
for (int i = 0;i<t.length();i++){ // 檢驗 t 中新增進去的字元
char ch = t.charAt(i);
if (map.containsKey(ch)&&map.get(ch)>0)
map.put(ch,map.get(ch)-1); // 如果字元在 map 中存在,並且個數大於0,則個數減一
else return ch; // 否則為新增進去的那個字元,直接返回
}
return ' ';
}
}
2.3 演算法執行結果
演算法簡單是簡單,結果也很殘忍,時間上只擊敗8.17%的使用者,不行~~~還得想想其他思路提升效能。下面是將儲存方法改為陣列儲存,因為題目限制了只有小寫字母,所有用26長度的 int 陣列就可以達到統計個數的目的。
public class Solution {
public char findTheDifference(String s, String t) {
int[] count = new int[26]; // 定義陣列儲存個數
for (int i = 0;i<s.length();i++){ // 同時對 s 和 t 中字元個數統計
count[s.charAt(i)-'a']++; // s 中的字元相應位置加1
count[t.charAt(i)-'a']--; // t 中的字元相應位置減1
}
count[t.charAt(t.length()-1)-'a']--; // t 中最後一個字元相應位置減1
for (int i = 0;i<26;i++){ // 查詢新增的字元
if (count[i]==-1)
return (char)(i+'a'); // 個數為-1的即為新增的字元,其他都是0
}
return ' ';
}
}
速度上得到了不小的提升,不過還不是很理想。再去參考參考別的大神的題解看看…
三、解題思路2(位運算)
3.1 題目理解分析
這題說的是字串 t 只比 s 多了一個字元,其他字元他們的數量都是一樣的,如果我們把字串 s 和 t 合併就會發現,除了那個多出的字元出現奇數次,其他的所有字元都是出現偶數次,這種情況我們就可以用異或運算來解決啦。
-
異或運算的三點規律:
1.a^a=0:任何數字和自己異或都是0
2.a^0=a:任何數字和0異或還是自己
3.aba=aab:異或運算具有交換律
-
用題目示例一舉例
s = “abcd”,t = “abcde”,合併之後為 “abcdabcde” ,每一位都進行異或運算為 abcdabcde ,再利用上述規律3 可以交換為 aabbccdde ,再用規律1可以得到 0000e ,最後由規律2得到最後結果為 e。
3.2 詳細程式碼(Java)
public class Solution {
public char findTheDifference(String s, String t) {
char[] chars = s.concat(t).toCharArray(); // 合併 s 和 t 並且轉化為 char 陣列
char result = 0; // 定義輸出結果的字元
for (char aChar : chars) {
result ^= aChar; // 對每一個字元進行異或操作
}
return result; // 返回保留結果的字元
}
}
3.3 演算法執行結果
程式碼少就算了,效能還直接飆升100%,所以位運算還是得掌握啊!!!
四、總結
感覺任何事情都是這樣的,你拍腦門就能想到的事情,很多人也同樣能輕鬆想到,並且肯定並不是很好的。方法稍微高階一點的,它掌握起來可能更費力一點,但帶給你的結果肯定也是可觀的。跟生活中的很多道理類似…