LeetCode 每日一題「判定字元是否唯一」

陳皮的JavaLib發表於2021-06-13

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

在這裡插入圖片描述

上一題與下一題

上一題LeetCode 每日一題「實現 strStr()」

下一題LeetCode 每日一題「判定是否互為字元重排」

相關文章