簡體   English   中英

確定字符串是否具有唯一字符

[英]determine if string has unique characters

該問題要求“實施一種算法來確定字符串是否具有所有唯一字符。

我看到了解決方案,但不太明白。

public boolean isUniqueChars(String str) {
    if (str.length() > 256) return false;
    boolean[] char_set = new boolean[256];
    for (int i = 0; i < str.length(); i++) {
        int val = str.charAt(i);
        if (char_set[val])
            return false;
        char_set[val] = true;
    }
    return true;
}

我們不是在代碼前面使用parseInt(int)轉換器嗎? str.charAt[i]會自動更改為int嗎?) boolean[] char set=new boolean[256]是什么意思? 為什么我們需要設置char_set[val]=true

我們還可以使用HashSet數據結構來確定字符串是否具有 java 中的所有唯一字符。

Set testSet = new HashSet();

for (int i = 0; i < str.length(); i++) {
    testSet.add(new Character(str.charAt(i)));
}

if (testSet.size() == str.length()) {
    System.out.println("All charcaters are Unique");
} else {
    System.out.println("All charcaters are niot unique");
}

請參閱我在評論中的解釋,因為您只標記了algorithm ,我假設沒有語言,只是解決算法本身:

public boolean isUniqueChars(String str){

   //more than 256 chars means at least one is not unique
   //please see first comment by @Domagoj as to why 256 length
    if(str.length()>256) return false;  

        //keeping an array to see which chars have been used
        boolean[] char_set = new boolean[256];

        //iterating over the string
        for(int i=0; i<str,length;i++){

            //not sure what language this is, but let's say it returns an
            //int representation of the char
            int val=str.charAt(i);

            //meaning this has been set to true before, so this char is not unique
            if(char_set[val]) 
                //nope, not unique
                return false;

            //remember this char for next time
            char_set[val]=true;
        } 

    //if we reached here, then string is unique
    return true;
}

一個簡單的解決方案是將 String 轉換為 Set 並比較相應對象的長度。 使用Java 8:

private static boolean checkUniqueChars(String copy) {
    if(copy.length() <= 1) return true;
    Set<Character> set = copy.chars()
       .mapToObj(e->(char)e).collect(Collectors.toSet());
    if (set.size() < copy.length()){
        return false;
    }
    return true;
}

您可以做的一種方法是通過位。

時間復雜度:O(N)(你也可以說時間復雜度是 0(1),因為 for 循環永遠不會遍歷超過 128 個字符。)
空間復雜度:O(1)

將每個字符視為位(無論是否存在)。 例如,我們需要檢查“abcada”中的所有字符是否都是唯一的,所以如果我們要檢查一個字符的位是否已經打開,如果是,那么我們返回 false 否則設置該位。

現在我們怎么做呢? 所有字符都可以表示為數字,然后是位。 我們將使用“set bit”和“get bit”方法。

在下面的代碼中,我們將假設該字符串僅使用小寫字母 a 到 z。

public static boolean isUniqueChars(String str) {
    int mask = 0;
    for (int i = 0; i < str.length(); ++i) {
        int val = str.charAt(i) - 'a'; // you will get value as 0, 1, 2.. consider these as the positions inside your mask which you need to check if the bit is set or not
        if ((mask & (1 << val)) > 0) return false; // Check if the bit is already set
        mask |= (1 << val); // Set bit
    }
    return true;
}

要了解位操作,您可以參考

https://www.hackerearth.com/practice/notes/bit-manipulation/

https://snook.ca/archives/javascript/creative-use-bitwise-operators

我花了一段時間才理解這些信息,但一旦我理解了,就大開眼界。 您可以使用比特解決這么多問題,並提供最優化的解決方案。

想想你將如何用紙和鉛筆做到這一點。

寫出字母一次。

然后逐個字符地檢查你的字符串。

當你到達一個字符時,把它從你的字母表中划掉。

如果你去划掉一個字符,發現它已經被划掉了,那么你知道這個字符以前出現在你的字符串中,然后你可以停下來。

這基本上就是您發布的代碼使用數組所做的。 該操作在 O(N) 時間內完成,額外空間為 O(K)(其中K是您擁有的鍵的數量)。

如果您的輸入有大量元素,或者您無法提前知道它們是什么,您可以使用哈希表來跟蹤哪些元素已經被看到。 這又需要 O(N) 時間和 O(cK) 額外空間,其中K是鍵的數量, c是大於 1 的某個值。

但是哈希表會占用相當多的空間。 還有另一種方法可以做到這一點。 對數組進行排序,這將花費 O(N log N) 時間,但不需要額外空間。 然后遍歷數組檢查是否有兩個相鄰的字符相同。 如果是這樣,你有一個副本。

您可以在我的博文中查看詳細說明: 檢查字符串是否具有所有唯一字符

最簡單的解決方案是循環遍歷所有字符,使用 hashMap 並將每個字符放入 hashmap 表中,在此之前檢查字符是否已經存在。 如果角色已經存在,則它不是唯一的。

公共類 UniqueString {

public static void main(String[] args) {

    String input = "tes";
    Map<String, Integer> map = new HashMap<String, Integer>();

    for (int i = 0; i < input.length(); i++) {

        if (!map.containsKey(Character.toString(input.charAt(i)))) {
            map.put(Character.toString(input.charAt(i)), 1);
        } else {            
            System.out.println("String has duplicate char");
            break;
        }
    }   
}

}

Java SE 9

您可以簡單地將字符串的長度與不同元素的數量相匹配。 為了獲取所有字符的IntStream ,您可以使用String#chars ,您可以在其上應用Stream#distinct來獲取唯一元素的Stream 確保將字符串轉換為單個大小寫(大寫/小寫),否則函數Stream#distinct將無法將不同情況下的相同字符(例如Ii )計為一個。

演示:

import java.util.stream.Stream;

public class Main {
    public static void main(String[] args) {
        // Test
        Stream.of(
                    "Hello", 
                    "Hi", 
                    "Bye", 
                    "India"
                ).forEach(s -> System.out.println(s + " => " + hasUniqueChars(s)));
    }

    static boolean hasUniqueChars(String str) {
        return str.toLowerCase().chars().distinct().count() == str.length();
    }
}

輸出:

Hello => false
Hi => true
Bye => true
India => false

Java SE 8

static boolean hasUniqueChars(String str) {
    return Arrays.stream(str.toLowerCase().split("")).distinct().count() == str.length();
}

為了獲得最佳性能,您應該使用Set並將字符串的字符添加到集合中。 如果set.add(...)方法返回false ,則表示給定字符之前已經見過,因此返回false ,否則在添加所有字符后返回true

對於簡單的解決方案,請使用Set<Character>

public static boolean allUniqueCharacters(String input) {
    Set<Character> unique = new HashSet<>();
    for (int i = 0; i < input.length(); i++)
        if (! unique.add(input.charAt(i)))
            return false;
    return true;
}

但是,這不會處理 BMP 之外的 Unicode 字符,例如 Emojis,因此我們可能希望更改該集合以使用 Unicode 代碼點:

public static boolean allUniqueCodePoints(String input) {
    Set<Integer> unique = new HashSet<>();
    return input.codePoints().noneMatch(cp -> ! unique.add(cp));
}

然而,即使是代碼點也不代表我們人類所認為的“字符”。 為此,我們需要處理 Grapheme Clusters:

public static boolean allUniqueClusters(String input) {
    BreakIterator breakIterator = BreakIterator.getCharacterInstance(Locale.US);
    breakIterator.setText(input);
    Set<String> unique = new HashSet<>();
    for (int start = 0, end; (end = breakIterator.next()) != BreakIterator.DONE; start = end)
        if (! unique.add(input.substring(start, end)))
            return false;
    return true;
}

或使用 Java 9+:

public static boolean allUniqueClusters(String input) {
    Set<String> unique = new HashSet<>();
    return Pattern.compile("\\X").matcher(input).results()
                  .noneMatch(m -> ! unique.add(m.group()));
}

在 JS 中,

const isStringUnique = str => {
      if(str){
          let obj = {}
          for(let char of str){
              obj[char] ? obj[char]++ : obj[char]=1;
          }
          
          for(let char of str){
              if(obj[char] > 1)
                return false;
          }
           return true;
          }
   return true;    
}
public class CheckStringUniqueChars {

    public static boolean checkUnique(String str) {
        int i=0,j=str.length()-1;
        while(i<j) {
            if(str.charAt(i) == str.charAt(j)) {
                return false;
            }
            i++;
            j--;
        }
        return true;
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM