LeetCode 每日一題「判定字元是否唯一」
我是陳皮,一個在網際網路 Coding 的 ITer,微信搜尋「陳皮的JavaLib」第一時間閱讀最新文章,回覆【資料】,即可獲得我精心整理的技術資料,電子書籍,一線大廠面試資料和優秀簡歷模板。
題目
實現一個演算法,確定一個字串 s 的所有字元是否全都不同。
示例1:
- 輸入: s = "leetcode"
- 輸出:false
示例2:
- 輸入:s = "abc"
- 輸出:true
限制
- 0 <= len(s) <= 100
- 如果你不使用額外的資料結構,會很加分。
題目來源:LeetCode
解法一
判斷一個字串中所有字元是否唯一,最簡單的暴力求解就是兩兩對比是否相同,即雙重迴圈,但是演算法複雜度為 O(n^2),效能也是最低的。如果字串的長度是比較小的話,此演算法也是勉強可以使用的。
package com.chenpi; /** * @Description 實現一個演算法,確定一個字串 s 的所有字元是否全都不同。 * @Author Mr.nobody * @Date 2021/4/18 * @Version 1.0 */ public class StrIsUnique { public boolean isUnique(String astr) { // 字串為null或者為空,自然沒有字元重複,即唯一 if (null == astr || 0 == astr.length()) { return true; } // 雙重迴圈,兩兩對比 for (int i = 0; i < astr.length() - 1; i++) { for (int j = i + 1; j < astr.length(); j++) { if (astr.charAt(i) == astr.charAt(j)) { return false; } } } return true; } public static void main(String[] args) { String astr = "leetcode"; StrIsUnique strIsUnique = new StrIsUnique(); System.out.println(strIsUnique.isUnique(astr)); } }
解法二
既然是判斷唯一性,那我們可以遍歷每一個字元,然後通過某種規則將它們放入指定位置,因為相同字元肯定會被放到相同的位置,我們只需要判斷放入此位置之前是否有字元放入過,如果有,就代表有重複的字元。藉助散列表這種資料結構就能達到這種效果。
package com.chenpi; import java.util.HashMap; import java.util.Map; /** * @Description 實現一個演算法,確定一個字串 s 的所有字元是否全都不同。 * @Author Mr.nobody * @Date 2021/4/18 * @Version 1.0 */ public class StrIsUnique { public boolean isUnique(String astr) { // 字串為null或者為空,自然沒有字元重複,即唯一 if (null == astr || 0 == astr.length()) { return true; } Map<Character, Integer> map = new HashMap<>(astr.length() + 1); // 遍歷每一個字元,從map中判斷是否存在相同的字元 for (int i = 0; i < astr.length(); i++) { // 存在相同的字元 if (null != map.get(astr.charAt(i)) && map.get(astr.charAt(i)) == 1) { return false; } // 在map中不存在此字元,放入map中 map.put(astr.charAt(i), 1); } return true; } public static void main(String[] args) { String astr = "陳皮的JavaLib"; StrIsUnique strIsUnique = new StrIsUnique(); System.out.println(strIsUnique.isUnique01(astr)); } }
解法三
如果我們不再借助其他資料結構,如何解法呢?因為要求唯一性,肯定要有字元比較的。解法二我們藉助了散列表這種資料結構,結果記憶體消耗方面只擊敗了27.28%的使用者。
假設字串中的字元是26個小寫字母,解法二是將每一個字元放入散列表中,如果散列表中每一個位置都沒有重複的字元,則唯一性。那我們可以將每一個字元對映到一個二進位制陣列中,通過與運算,如果相同位置都為1,則結果為1,則代表有重複字元。
藉助一個初始值為0的int變數mark,二進位制形式為0000...0000,遍歷每一個字元,計算字元與a
字元的距離move_bit,然後使用左移運算子1 << move_bit建立對應下標為1,其餘下標為0的數num。將num與mark做與運算,如果結果不為0,則代表有重複字元。如果結果為0,則代表這個字元之前沒出現過,將num和mark通過或運算的結果賦值給mark,即在mark中將此字元的對應下標的值設為1。
package com.chenpi;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BinaryOperator;
/**
* @Description 實現一個演算法,確定一個字串 s 的所有字元是否全都不同。
* @Author Mr.nobody
* @Date 2021/4/18
* @Version 1.0
*/
public class StrIsUnique {
public boolean isUnique02(String astr) {
// 字串為null或者為空,自然沒有字元重複,即唯一
if (null == astr || 0 == astr.length()) {
return true;
}
int mark = 0;
int num = 0;
// 遍歷每一個字元
for (int i = 0; i < astr.length(); i++) {
num = 1 << (astr.charAt(i) - 'a');
// 通過與運算判斷對應下標是否都為1,即是否有相同字元
if ((mark & num) != 0) {
return false;
}
// 在map中將對應下標置為1
mark |= num;
}
return true;
}
public static void main(String[] args) {
String astr = "javalib";
StrIsUnique strIsUnique = new StrIsUnique();
System.out.println(strIsUnique.isUnique02(astr));
}
}