我是陳皮,一個在互聯網 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));
}
}