본문 바로가기

카테고리 없음

[LeetCode] - 242. Valid Anagram

LeetCode는 프로그래밍 문제를 풀며 코딩 실력을 향상할 수 있는 온라인 플랫폼입니다. 다양한 알고리즘 및 데이터 구조 문제를 제공하며, 면접 대비에 유용합니다. 해당 문제는, LeetCode Problems에서 볼 수 있는 난이도 '쉬움 (Easy)' 단계인 "Valid Anagram" 문제입니다.

--> https://leetcode.com/problems/valid-anagram/description/

 

문제 : 

Given two strings s and t, return true if t is an anagram of s, and false otherwise.

An Anagram is a word or phrase formed by rearranging the letters of a different word or phrase, typically using all the original letters exactly once.


Example 1 :

Input : s = "anagram", t = "nagaram"

Output : true

 

Example 2 :

Input : s = "rat", t = "car"

Output : false

 

Constraints :

  • 1 <= s.length, t.length <= 5 * 10^4
  • s and t consist of lowercase English letters.
  •  

Follow up :

What if the inputs contain Unicode characters?

How would you adapt your solution to such a case?


이 문제는 두 문자열 s와 t가 주어질 때, t가 s의 애너그램(Anagram)인지 확인하는 문제입니다. 애너그램은 다른 단어나 구문의 문자를 다시 배열하여 형성된 단어나 구문을 의미하며, 원래의 모든 문자를 정확히 한 번 사용해야 합니다.

 

class Solution {
    public boolean isAnagram(String s, String t) {
        if (s.length() != t.length()) {
            return false;
        }
        Map<Character, Integer> charCountS = new HashMap<>();
        Map<Character, Integer> charCountT = new HashMap<>();
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            charCountS.put(c, charCountS.getOrDefault(c, 0) + 1);
        }

        for (int i = 0; i < t.length(); i++) {
            char c = t.charAt(i);
            charCountT.put(c, charCountT.getOrDefault(c, 0) + 1);
        }
        return charCountS.equals(charCountT);
        
    }
}

 

이 코드는 두 문자열 s와 t가 애너그램인지 확인하기 위해 두 개의 해시맵을 사용하여 각 문자열의 문자 빈도를 추적합니다. 각 문자열의 빈도 해시맵을 비교하여 두 문자열이 애너그램인지 확인합니다.

  1. 문자열 길이 비교 :
    • 두 문자열 s와 t의 길이가 다르면 애너그램이 될 수 없으므로 바로 false를 반환합니다.
  2. 문자 빈도 계산 :
    • 두 개의 해시맵 charCountS와 charCountT를 사용하여 각각의 문자열에 대한 문자 빈도를 계산합니다.
     
    • 첫 번째 문자열 s에 대해 각 문자의 빈도를 계산하고 해시맵 charCountS에 저장합니다.
     
    • 두 번째 문자열 t에 대해 각 문자의 빈도를 계산하고 해시맵 charCountT에 저장합니다.
     
  3. 빈도 비교 :
    • 두 해시맵 charCountS와 charCountT가 같은지를 비교합니다. 만약 두 해시맵이 동일하다면, 두 문자열은 애너그램입니다. 그렇지 않으면 애너그램이 아닙니다.

시간 복잡도 :

  • O(n) : 여기서 n은 문자열의 길이입니다.
    • 문자열 s와 t를 각각 한 번씩 순회하면서 각 문자의 빈도를 계산하므로, O(n) 시간이 소요됩니다.
    • 해시맵의 put 연산은 평균적으로 O(1)이므로, 전체 시간 복잡도는 O(n)입니다.

공간 복잡도

  • O(1) 또는 O(m) : 여기서 m은 사용된 고유 문자의 수입니다.
    • 영어 소문자만 사용된다면 공간 복잡도는 O(1)입니다. (고정된 26개의 문자를 사용하므로)
    • 일반적으로 문자의 종류가 많아질수록 해시맵 크기가 커질 수 있지만, 해시맵은 각 문자열의 문자 빈도를 저장하므로 최대 m개의 키-값 쌍을 가질 수 있습니다.

코드의 장단점

장점

  • 유연성 : 유니코드 문자나 다양한 문자셋을 지원하기 위해 해시맵을 사용할 수 있습니다.
  • 직관성 : 두 해시맵을 사용하여 문자열의 빈도를 비교하는 방식은 직관적이며 이해하기 쉽습니다.

단점

  • 공간 사용 : 두 개의 해시맵을 사용하므로 공간 사용이 두 배가 됩니다. 하지만 각 문자열에 대해 별도의 빈도 맵을 유지하기 때문에 두 문자열이 매우 클 경우 공간 사용이 증가할 수 있습니다.

그래서 개선한 코드가 이겁니다 : 

class Solution {
    public boolean isAnagram(String s, String t) {
        if (s.length() != t.length()) {
            return false;
        }
        
        int[] charCount = new int[26];  // 소문자 영어 알파벳에 대한 카운트 배열
        
        // 문자열 s의 각 문자에 대해 카운트를 증가
        for (char c : s.toCharArray()) {
            charCount[c - 'a']++;
        }
        
        // 문자열 t의 각 문자에 대해 카운트를 감소
        for (char c : t.toCharArray()) {
            charCount[c - 'a']--;
        }
        
        // 모든 카운트가 0인지 확인
        for (int count : charCount) {
            if (count != 0) {
                return false;  // 0이 아니면 애너그램이 아님
            }
        }
        
        return true;  // 모든 카운트가 0이면 애너그램임
    }
}

 

이 코드는 두 문자열 s와 t가 애너그램인지 확인하는 효율적인 방법을 제공합니다. 이 방법은 각 문자열의 문자의 빈도를 비교하여 두 문자열이 같은 문자를 같은 빈도로 포함하고 있는지를 검사합니다. 이 방법은 정렬을 사용하는 방법보다 더 효율적이며, O(n) 시간 복잡도를 가집니다.

  1. 길이 비교 :
    • 두 문자열의 길이가 다르면 애너그램이 될 수 없으므로 즉시 false를 반환합니다.
  2. 문자 빈도 카운트 배열 초기화 :
    • 길이가 26인 정수 배열 charCount를 생성하여 각 문자의 빈도를 저장합니다.
    • 이 배열의 인덱스는 문자 'a'부터 'z'까지의 알파벳 순서와 대응됩니다.
  3. 문자 빈도 증가 :
    • 문자열 s의 각 문자에 대해 해당 문자의 빈도를 증가시킵니다.
    • c - 'a'를 사용하여 문자 c의 인덱스를 계산합니다. 예를 들어, 'a'는 인덱스 0, 'b'는 인덱스 1이 됩니다.
  4. 문자 빈도 감소 :
    • 문자열 t의 각 문자에 대해 해당 문자의 빈도를 감소시킵니다.
    • 증가한 s의 빈도와 감소한 t의 빈도가 정확히 일치해야 애너그램이 성립됩니다.
  5. 빈도 비교 :
    • charCount 배열을 순회하면서 모든 값이 0인지 확인합니다.
    • 하나라도 0이 아닌 값이 있다면 두 문자열은 애너그램이 아닙니다.
  6. 애너그램 확인 :
    • 모든 빈도가 0이라면 두 문자열은 애너그램으로, true를 반환합니다.

시간 복잡도

  • O(n) : 여기서 n은 문자열의 길이입니다.
    • s와 t를 각각 한 번씩 순회하면서 문자의 빈도를 증가 및 감소하므로, 전체적으로 O(n)의 시간 복잡도를 가집니다.

공간 복잡도

  • O(1) : 고정 크기 배열(26)을 사용하므로 상수 공간을 사용합니다.
    • 알파벳의 개수는 고정되어 있어 입력 크기에 상관없이 공간 복잡도가 일정합니다.

코드들의 Runtime 결과