1. 程式人生 > 其它 >力扣389-找不同(Java詳細題解,位運算100%)

力扣389-找不同(Java詳細題解,位運算100%)

技術標籤:演算法刷題字串java演算法leetcode

力扣389-找不同

一、原題題目

1.1 題目

  給定兩個字串 st,它們只包含小寫字母。字串 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
  • st 只包含小寫字母

來源:力扣(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%,所以位運算還是得掌握啊!!!

四、總結

  感覺任何事情都是這樣的,你拍腦門就能想到的事情,很多人也同樣能輕鬆想到,並且肯定並不是很好的。方法稍微高階一點的,它掌握起來可能更費力一點,但帶給你的結果肯定也是可觀的。跟生活中的很多道理類似…