about. What I learned/about.Algorithm

[백준 10808] 알파벳 숫자 세기

#1. 조건

단어 길이가 100을 넘지 않는 문자열이 주어진다. 문자열은 모두 소문자로 주어진다. 

단어에 존재하는 알파벳이 몇개인지 개수를 체크하라

#2. 풀이

[나의 풀이]

길이가 26인 빈배열을 생성하고 소문자 아스키코드를 초기화 시켰다(97 ~ 122). 그리고 string 으로 받은 문자의 길이만큼 For문을 돌리면서 아스키 코드와 단어의 알파벳을 비교하였다. 

 

[좀 더 좋은 풀이]

97부터 122까지 배열을 초기화 시키기 보다는 모든 알파벳의 첫번째 값인 'a'를 단어가 가진 알파벳에서 빼면 0~26중 하나의 값이 나온다. 이렇게되면 길이가 26인 배열만 선언해 놓고 문자에서 추출한 알파벳에서 'a'(97)를 빼주면 인덱스가 나온다. 해당 인덱스를 ++해주면 다른 행위를 하지 않아도 갯수를 셀 수 있다. 

#3. 코드

#include<bits/stdc++.h>
using namespace std;

// 좋은 풀이
int chr[26];
string str;

// 0 ~ 26까지 배열이 필요한데 a는 97이다. 
// 그래서 해당 소문자에서 'a'를 빼게 되면 Int로 오토박싱됨
int main(){
    cin >> str;
    for ( char alpa : str){
        chr[alpa - 'a'] ++;
    }

    for ( int b : chr){
        cout << b << " ";
    }
}

// 나의 풀이
int a[26];
int result[26];
// 97 ~ 122 ( a ~ z )
int main(){
    string s = "";
    cin >> s;
    a[0] = 97;
for ( int i = 1; i < 26; i++){
    a[i] = a[i-1] + 1;
    }

for ( int i = 0 ; i < 26; i++){
    for ( int j = 0 ; j < s.size(); j++){
        if (a[i] == s[j]){
            result[i] += 1;
        }
    }
}
for (int x : result){
    cout << x << " ";
}
}

#4. 설명

해당 알파벳은 몇개.

해당 알파벳 : 몇개

         key    : value

map, set, 카운팅 배열을 사용할 수 있다.

좌표이동이라는 개념이 들어간다. 좌표이동은 멀리있는 좌표를 가운데로 끌고 오는 것이다. 위의 예처럼 97 ~122의 범위의 숫자에 맨 머리 숫자인 97을 빼개되면 0~ 26이라는 숫자가 남게되고 97 ~ 122의 좌표를 대신할 수 있게된다. 

#5. 사고 과정

아직은 단순한 사고에 불과해서 오래걸렸다. 하지만 기준을 잡아야한다는 것을 알았다.

 

배열을 두개 만들고 하나의 배열에는 소문자의 아스키코드(a to z)를 담았다. 아스키코드와 단어의 알파벳을 비교하면서 결과 값을 담을 배열도 만들었따. 일을 두번한 것과 같다. 결과 값을 따로 담을 필요 없이 좌표이동을 통해 인덱스를 각 알파벳의 위치로 정한다. 단어에서 꺼낸 알파벳에서 알파벳 중 가장 초기값인 'a'를 빼면 해당 알파벳의 인덱스가 나오게되고 해당 인덱스의 값을 ++ 해주기만 하면된다.