https://www.acmicpc.net/problem/1919

 

1919번: 애너그램 만들기

두 영어 단어가 철자의 순서를 뒤바꾸어 같아질 수 있을 때, 그러한 두 단어를 서로 애너그램 관계에 있다고 한다. 예를 들면 occurs 라는 영어 단어와 succor 는 서로 애너그램 관계에 있는데, occurs

www.acmicpc.net

 

Sol 1)

문제 조건을 보면 소문자가 주어지니까 한글자씩 비교하면서, 같은 글자가 존재하면 이를 'A'로 바꿔버린다. 

예를들어, dared와 bread라고 하면

d a r e d

b r e a d

A A A A d

b A A A A

로 바뀌게 되는 것이다. 이제 b,d 두 문자만 남으므로 2개를 제거하는 것이 답이다.

 

a a b b c c

x x y y b b 

이면,

a a A A c c 

x x y y A A

로 바뀌니까 총 8개이다.

 

코드로 작성해보면,

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import java.util.Scanner;
 
public class Main {
 
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String str1 = sc.next();
        String str2 = sc.next();
        char[] char1 = str1.toCharArray();
        char[] char2 = str2.toCharArray();
        int cnt = 0;
        for (int i = 0; i < char1.length; i++) {
            for (int j = 0; j < char2.length; j++) {
                if (char1[i] == char2[j]) {
                    char1[i] = 'A';
                    char2[j] = 'A';
                }
            }
        }
        for (int i = 0; i < char1.length; i++) {
            if (char1[i] != 'A') {
                cnt++;
            }
        }
        for (int i = 0; i < char2.length; i++) {
            if (char2[i] != 'A') {
                cnt++;
            }
        }
 
        System.out.println(cnt);
    }
 
}
 
cs

 

 

Sol 2)

애너그램이라는게 결국 알파벳의 종류, 그 개수가 완전히 같은 단어이므로

각 단어에서 어떤 알파벳을 가지고 있고, 각각 몇개씩 가지고 있는지를 비교하도록 한다.

예를들어,

dared: 'a': 1, 'b': 0, 'd': 2, 'e': 1, 'r': 1 이고

bread: 'a': 1, 'b': 1, 'd': 1, 'e': 1, 'r': 1 이다.

알파벳의 종류와 그 개수가 동일하다면 제거할 필요가 없다. 즉 신경쓸 필요가 없다.

종류와 개수가 다른 경우만 체크해주면 된다.

즉, b와 d만 비교해주고, 그 개수의 차이만큼만 제거해주면 된다. (b 1개, d 1개 총 2개)

 

코드로 작성해보자.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import java.util.Scanner;
 
public class Main {
 
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String str1 = sc.next();
        String str2 = sc.next();
        
        /* 
        알파벳 카운트되는 배열만들기
        index 0 1 2 3 4 5 ... 25
        count 
        알파벳  a b c d e f ... z
        
        int[] arr = new int[26]; 에서
        어떤 단어가 bear이다?
        {1, 1, 0, 0, 1.... } 이런식으로 카운트를 표시!
        
        */
         
        int[] alphaArr1 = new int[26]; // 알파벳 개수(26개)
        for (int i = 0; i < str1.length(); i++) {
            alphaArr1[str1.charAt(i) - 'a']++;
        }
        
        int[] alphaArr2 = new int[26]; // 알파벳 개수(26개)
        for (int i = 0; i < str2.length(); i++) {
            alphaArr2[str2.charAt(i) - 'a']++;
        }
        
        int ans = 0;
        for (int i = 0; i < 26; i++) {
            if(alphaArr1[i] > alphaArr2[i]) {
                ans += alphaArr1[i] - alphaArr2[i];
            }
            else if(alphaArr1[i] < alphaArr2[i]) {
                ans += alphaArr2[i] - alphaArr1[i];
            }
        }
        
        System.out.println(ans);
        
    }
 
}
 
cs

 

위 코드에서 사용된 중요한 생각!

int[ ] arr = new int [ 26 ];을 만드는 부분

그 결과를 아래 그림처럼 생각해라

첫번째 행은 a,b,c...처럼 알파벳의 위치로 생각하는 부분

두번째 행은 초기값은 다 0이지만, 카운트가 되면 1씩 증가시키는 부분

세번째 행은 index number

 

Sol 2-1)

위 코드를 좀 더 간결하게 만들기 위해 함수를 사용해보자.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import java.util.Scanner;
 
public class Main {
 
    public static int[] get_alphabet_count(String str) {
        int[] count = new int[26];
        for (int i = 0; i < str.length(); i++) {
            count[str.charAt(i) - 'a']++;
        }
        return count;
    }
 
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String str1 = sc.next();
        String str2 = sc.next();
 
        int[] alphaArr1 = get_alphabet_count(str1);
        int[] alphaArr2 = get_alphabet_count(str2);
 
        int ans = 0;
        for (int i = 0; i < 26; i++) {
            ans += Math.abs(alphaArr1[i] - alphaArr2[i]); // 차이 구하기 위해 절댓값 사용
        }
 
        System.out.println(ans);
 
    }
 
}
 
cs

https://www.acmicpc.net/problem/2744

 

2744번: 대소문자 바꾸기

영어 소문자와 대문자로 이루어진 단어를 입력받은 뒤, 대문자는 소문자로, 소문자는 대문자로 바꾸어 출력하는 프로그램을 작성하시오.

www.acmicpc.net

 

문제를 풀기에 앞서 ASCII Code에 대해서 필요한 정보를 정리하고 넘어가자.

간단하게 char에 해당되는 정수 값이 존재한다고 생각하면 된다.

예를 들어, 문자 A의 ASCII Code 값은 65이다.

아래 테이블을 참고하자.

 

 

중요한건, 문제를 풀 때, 각 문자에 해당되는  ASCII Code 값을 알아야하는 게 아니라는 것이다.

어떻게 활용하면 되는가?

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package String;
 
public class StringClass {
    
    public static void main(String[] args) {
        
        // ASCII Code값을 char 변수에 넣으면, 그 변수에 ASCII Code값에 해당하는 문자가 저장된다.
        char x = 65;
        System.out.println(x); // A
        
        // 문자끼리 연산이 가능 -> 문자 사이의 간격만큼 결과가 나타남
        int n = 'Z' - 'A';
        System.out.println(n); // 25 -- A는 1번째, Z는 26번째 문자니까
        
        // char와 int 사이에 연산이 가능
        System.out.println(x + 25); // 90
        
        // 문자끼리 대소비교가 가능(ASCII Code 값으로 대소비교)
        System.out.println('A' < 'Z'); // true
        
        // Casting
        // char를 int로 형변환 가능(ASCII Code 값 저장)
        System.out.println((int)x); // 65
        
        // int를 char로 형변환 가능(ASCII Code 값이 해당 int 값인 char이 반환)
        System.out.println((char)(x + 25)); // Z (ASCII Code값이 90)
    }
}
 
cs

 

이를 활용하여 간단하게 대소문자를 변환해보자.

중요한 생각은 A와 Z 사이의 간격은 a와 z 사이의 간격과 같다는 것!

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package String;
 
public class StringClass {
    
    public static void main(String[] args) {
        
        String str = "AbCdEf";
        for (int i = 0; i < str.length(); i++) {
            // 대문자의 경우!
            if('A' <= str.charAt(i) && str.charAt(i) <= 'Z') {
//                int dist = str.charAt(i) - 'A';    // A와의 간격
                System.out.print((char)('a' + str.charAt(i) - 'A')); // a로부터 해당 간격만큼 떨어진 문자로!
            } 
            else {
                System.out.print((char)('A' + str.charAt(i) - 'a'));
            }
        }
    }
}
 
cs

 

AbCdEf가 aBcDeF로 변환됨을 알 수 있다.

 

이제 [BOJ] 2744. 대소문자 바꾸기 문제를 풀어보자.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import java.util.Scanner;
 
public class Main {
 
    public static void main(String[] args) {
 
        Scanner sc = new Scanner(System.in);
        String str = sc.next();
        String answer = "";
        for (int i = 0; i < str.length(); i++) {
            if ('A' <= str.charAt(i) && str.charAt(i) <= 'Z') { // 대문자라면,
                answer += (char)('a' + str.charAt(i) - 'A');
            } else { // 소문자라면,
                answer += (char)('A' + str.charAt(i) - 'a');
            }
        }
        System.out.println(answer);
    }
 
}
cs

 

 

또는,

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import java.util.Scanner;
 
public class Main {
 
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String str = sc.next();
        char[] arr = str.toCharArray();
        for (int i = 0; i < str.length(); i++) {
            char ch = str.charAt(i);
            if('A' <= ch && ch <= 'Z') {
                arr[i] = (char)('a' + ch - 'A');
            } else {
                arr[i] = (char)('A' + ch - 'a');
            }
            
        }
        
        System.out.println(arr);
    }
 
}
 
cs

 

끝.

 

'알고리즘 및 코테 > 자료구조 및 알고리즘' 카테고리의 다른 글

[String] 문자열(Java)  (0) 2023.03.22

https://www.acmicpc.net/problem/1065

 

1065번: 한수

어떤 양의 정수 X의 각 자리가 등차수열을 이룬다면, 그 수를 한수라고 한다. 등차수열은 연속된 두 개의 수의 차이가 일정한 수열을 말한다. N이 주어졌을 때, 1보다 크거나 같고, N보다 작거나

www.acmicpc.net

 

이 문제를 풀면서 내가 예상하지 못한 무한루프에 빠지게 되었었다. 끝없는 고민 끝에 그 이유를 찾아냈고, 다시는 똑같은 잘못을 하지 않도록 그 이유를 기록하는 것에 목적을 두도록 한다.

 

먼저, 문제에서는 N이 1000보다 작거나 같긴 한데, 나는 좀 더 나아가서 N이 세자리수든 네자리수든 문제보다 더 큰 N이 왔을 때도 한수를 구할 수 있도록 코드를 작성해보고 싶었다.

 

먼저, 

내가 무한 루프에 빠지게 됐던 잘못된 코드를 저장해두도록 하겠다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
 
import java.util.Scanner;
 
public class Main {
 
    public static void main(String[] args) {
 
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();
        int count = 0;
        for (int i = 1; i <= N; i++) {
            String iStr = i + "";
            if (iStr.length() > 2) {
                int[] arr = new int[iStr.length()];
                int m = 0;
                while (i != 0) {
                    arr[m] = i % 10;
                    i = i / 10;
                    m++;
                }
                int k = arr[1- arr[0];
                boolean b = true;
                for (int j = 1; j < arr.length; j++) {
                    if (arr[j] - arr[j - 1!= k) {
                        b = false;
                    }
                }
                if (b) {
                    count++;
                }
 
            } else {
                count++;
            }
 
        }
        System.out.println(count);
 
    }
}
cs

 

어디서 잘못됐을까?

 

while (i != 0) {
arr[m] = i % 10;
i = i / 10;
m++;
}

이 부분에서 i의 자릿수를 줄여가며 각각의 일의 자리 수를 받아 배열에 저장하는 과정에서 결과적으로 i는 늘 0이 된다는 것을 놓쳤다...

이후 다시 i++이 되어 다시 i는 1부터 for문을 돌기 시작한다. 그리고 1 ~ 99까지는 count가 되지만, 100이 됐을 때 i는 다시 0이 되어버리고, 다시 1부터 for문을 도는...무한루프..

 

그래서 i 값을 다른 변수(int n)에 저장해두어서 그 변수를 통해 while문을 돌리도록 하였다.

그 결과 코드를 작성해보면 다음과 같다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
 
import java.util.Scanner;
 
public class Main {
 
    public static void main(String[] args) {
 
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();
        int count = 0;
        for (int i = 1; i <= N; i++) {
            String iStr = i + ""// 숫자가 몇자리 수인지를 파악하기 위해 문자열로 바꿔줬다.
            if (iStr.length() > 2) { // 세자리 수 이상의 경우!
                int[] arr = new int[iStr.length()]; // 자릿수 만큼의 배열의 크기를 갖는 배열 생성
                int m = 0// arr 배열의 인덱스의 역할을 하기 위한 변수 선언
                int n = i; // i값(파악하고자 하는 수)을 다른 변수에 저장해둔다.
                while (n != 0) {
                    arr[m] = n % 10// 일의 자리수를 배열에 하나씩 넣어준다.
                    n = n / 10;      // 자릿수를 줄여나가면서(예: 123 -> 12 -> 1 -> 0)
                    m++;              // 인덱스 증가시킴
                }
                int k = arr[1- arr[0]; // 등차수열을 이루는지 확인하기 위해 자릿수 사이의 차이를 하나 구해놓는다.
                boolean b = true;
                for (int j = 1; j < arr.length; j++) {
                    if (arr[j] - arr[j - 1!= k) {
                        b = false;    // 차이가 하나라도 다른게 있으면 false가 돼서 한수가 아닌 것으로 판단
                    }
                }
                if (b) { // 차이가 모두 일정하다는 것이므로 한수에 해당
                    count++;
                }
 
            } else { // 1 ~ 99 의 경우 그대로 한수가 된다.
                count++;
            }
 
        }
        System.out.println(count);
 
    }
}
cs

 

 

+ Recent posts