<4.4> 모든 아나그램 찾기

mutexlocking·2022년 10월 22일
0

section4의 문제를 순차적으로 풀어왔다면, 이 문제를 보았을 때
HashMap + TwoPointers + SlidingWindow를 사용하여
4.3 문제와 유사한 방법으로
아나그램 개수를 찾으면 된다는 것을 바로 파악할 수 있을 것이다.

일단 코드 먼저 ...

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

public class Main {

    public static boolean isAnagram(Map<Character, Integer> map1, Map<Character, Integer> map2){

        /**
         * 1. 일단 사용된 문자의 종류가 같아야 함
         * 2. 그리고 동시에 ->  각 종류별 문자의 사용 빈도수가 같아야 함
         * */

        if(map1.keySet().equals(map2.keySet())){
            for (Character key : map1.keySet()) {
                if(map1.get(key) != map2.get(key)){
                    return false;
                }
            }
        } else{
            return false;
        }

        return true;
    }

    public static int solution(char[] charArr, char[] part, Map<Character, Integer> mapOfPart){
        Map<Character, Integer> map = new HashMap<>();
        int cnt = 0;

        for(int i=0; i<part.length; i++){
            Integer frequency = map.getOrDefault(charArr[i], 0);
            map.put(charArr[i], frequency+1);
        }

        if(isAnagram(map, mapOfPart)){
            cnt++;
        }

        int lt = 0;
        int rt = part.length-1;

        while(rt < charArr.length-1){

            /** 여기서 빈도수가 0이면 아예 remove를 해줘야 -> isAnagram() 함수에서 -> 사용된 문자 종류의 개수가 같은걸로 판단된다. */
            if(map.get(charArr[lt])==1){
                map.remove(charArr[lt]);
            } else{
                map.put(charArr[lt], map.get(charArr[lt]) - 1);
            }

            lt++;
            rt++;

            Integer frequency = map.getOrDefault(charArr[rt], 0);
            map.put(charArr[rt], frequency+1);

            if(isAnagram(map, mapOfPart)){
                cnt++;
            }
        }

        return cnt;
    }

    public static void main(String[] args){

        //0. Scanner 준비
        Scanner sc = new Scanner(System.in);

        //1. 입력
        char[] charArr = sc.nextLine().toCharArray();
        char[] part = sc.nextLine().toCharArray();

        //2. part에 대한 빈도수를 partOfMap 에 기록
        Map<Character, Integer> partOfMap = new HashMap<>();
        for(int i=0; i<part.length; i++){
            Integer frequency = partOfMap.getOrDefault(part[i], 0);
            partOfMap.put(part[i], frequency+1);
        }

        //3. solution() 호출하여 결과 리턴
        int cnt = solution(charArr, part, partOfMap);

        //3. 결과 출력
        System.out.println(cnt);
    }
}

그런데 HashMap의 equals() 메소드는 , 이미 모든 (Key,Value) 의 쌍이 정확히 일치할 때 만 true를 리턴하도록 오버라이딩 되어 있다.
따라서 사용된 각 문자의 빈도수를 count할 때,
빈도수가 0이라면 (Key,Value)의 쌍을 아예 remove() 시키는 방식으로 count해나간다면
별도의 isAnagram() 같은 메소드 필요 없이,
HashMap의 equals() 메소드 자체만으로 아나그램 여부를 판별할 수 있다.

그렇게 isAnagram() 말고 , HashMap의 equals() 메소드를 사용하여 해결한 코드는 아래와 같다.

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

public class Main {

    public static boolean isAnagram(Map<Character, Integer> map1, Map<Character, Integer> map2){

        /**
         * 1. 일단 사용된 문자의 종류가 같아야 함
         * 2. 그리고 동시에 ->  각 종류별 문자의 사용 빈도수가 같아야 함
         * */

        if(map1.keySet().equals(map2.keySet())){
            for (Character key : map1.keySet()) {
                if(map1.get(key) != map2.get(key)){
                    return false;
                }
            }
        } else{
            return false;
        }

        return true;
    }

    public static int solution(char[] charArr, char[] part, Map<Character, Integer> mapOfPart){
        Map<Character, Integer> map = new HashMap<>();
        int cnt = 0;

        for(int i=0; i<part.length; i++){
            Integer frequency = map.getOrDefault(charArr[i], 0);
            map.put(charArr[i], frequency+1);
        }

        if(map.equals(mapOfPart)){
            cnt++;
        }

        int lt = 0;
        int rt = part.length-1;

        while(rt < charArr.length-1){

            /** 여기서 빈도수가 0이면 아예 remove를 해줘야 -> isAnagram() 함수에서 -> 사용된 문자 종류의 개수가 같은걸로 판단된다. */
            if(map.get(charArr[lt])==1){
                map.remove(charArr[lt]);
            } else{
                map.put(charArr[lt], map.get(charArr[lt]) - 1);
            }

            lt++;
            rt++;

            Integer frequency = map.getOrDefault(charArr[rt], 0);
            map.put(charArr[rt], frequency+1);

            if(map.equals(mapOfPart)){
                cnt++;
            }
        }

        return cnt;
    }

    public static void main(String[] args){

        //0. Scanner 준비
        Scanner sc = new Scanner(System.in);

        //1. 입력
        char[] charArr = sc.nextLine().toCharArray();
        char[] part = sc.nextLine().toCharArray();

        //2. part에 대한 빈도수를 partOfMap 에 기록
        Map<Character, Integer> partOfMap = new HashMap<>();
        for(int i=0; i<part.length; i++){
            Integer frequency = partOfMap.getOrDefault(part[i], 0);
            partOfMap.put(part[i], frequency+1);
        }

        //3. solution() 호출하여 결과 리턴
        int cnt = solution(charArr, part, partOfMap);

        //3. 결과 출력
        System.out.println(cnt);
    }
}
profile
개발자가 되고자 try 하는중

0개의 댓글