문자를 큰 것부터 작은 순으로 정렬을 하는 문제이다. 대문자는 소문자보다 작은 것으로 간주해서 소문자가 대문자보다 앞으로 나와야한다.
예시 ) "Zbcdefg" ➡️ "gfedcbZ"
처음에 생각했을 때는 아스키 코드를 사용해서 대문자와 소문자를 나눈 뒤, 소문자를 먼저 정렬한 문자열 뒤에 대문자를 정렬하여 붙이려고 했다.
그래서 if 문으로 대문자와 소문자를 나눠주었다.
if (s[i] > 64 && s[i] < 91) { ... } // 대문자
else if (s[i] > 96 && s[i] < 123) { ... } // 소문자
이렇게 아스키 코드를 사용해서 대문자와 소문자를 나누고 정렬을 하여 문자열에 붙여주었다.
하지만....
문자열을 그냥 정렬하면 기본값으로 대문자가 뒤로 정렬이 된다는 것을 몰랐다....
생각해보니 아스키코드를 보았을 때, [대문자 아스키코드 < 소문자 아스키코드] 이다..
그래서 큰 것부터 작은 것을 정렬하게 되면 당연하게 소문자가 먼저 정렬이 된다.
내림차순으로 정렬을 해야하기 때문에 Collections.reverseOrder()
를 사용하였다.
역시 참조형 클래스만 Collections.reverseOrder()
를 사용할 수 있다.
Arrays.sort(sArray, Collections.reverseOrder());
주어진 숫자 중 3개의 수를 더했을 때 소수가 되는 경우의 개수를 구하는 문제이다.
예시) [1, 2, 7, 6, 4] ➡️ 4
주어진 숫자 배열에서 3개의 숫자를 고르기 위해 삼중 반복문을 만들어주었다.
for (int i = 0; i < nums.length; i++) {
for (int j = i + 1; j < nums.length; j++) {
for (int k = j + 1; k < nums.length; k++) {
(...)
}
}
}
처음에는 더한 값을 Set에 넣어서 그 중에서 소수를 찾으려고 했다.
하지만 3개의 수를 더했을 때 소수가 되는 경우의 개수였기 때문에
1 + 2 + 4 = 7 , 2 + 4 + 1 = 7 이렇게 모두 7이 되지만 3개의 수를 골라 더했기 때문에 경우의 수가 될 수 있다.
문제를 잘 이해했던 것 같다.
그래서 처음부터 세 수를 더한 값이 소수인지 판별할 수 있도록 반복문 안에 코드를 작성하였다.
int sum = (nums[i] + nums[j] + nums[k]);
boolean check = false;
for (int n = 2; n * n <= sum; n++) {
if(sum % n == 0) check = true;
}
if(!check) answer++;
check
를 false
로 하고 true
일 때 answer
를 카운트(++) 하였다.
for
문으로 n < sum
으로 할 경우 돌지 않아도 되는 수도 돌게 된다.
100 = 10 * 10
을 생각해보면 10
까지만 돌면 된다는 것을 알 수 있다.
아이디를 규칙에 맞지 않을 경우 규칙에 맞게 유사한 아이디를 추천해줘야하는 문제이다.
1. 모든 대문자를 소문자로 치환
2. 알파벳 소문자, -, _, .를 제외한 모든 문자 제거
3. 연속되는 .을 하나의 .으로 치환
4. .가 처음이나 끝에 있다면 제거
5. 빈 문자열이라면 a 를 추가
6. 16자 이상이라면 앞에 15자를 제외한 나머지 문자 제거
7. 2자 이하라면 3자가 될 때까지 마지막 문자를 반복해서 끝에 추가
1단계는 toLowerCase()
를 사용해서 쉽게 할 수 있었다.
2단계에서 처음으로 정규표현을 사용하였다.
정규표현하는 것에도 순서가 있는지 어떻게 하면 맞게 제거되고 어떻게 하면 제거가 되지 않았다.
한 번에 바꾸기 위해 replaceAll()
을 사용하였다.
알파벳과 숫자, -, _, .
이 나올 수 있게
["\W|^.-_"]
이렇게 작성을 하였다... 정규표현식을 사용하는 법에 익숙하지 않아 어떤 식으로 사용해야할 지 몰랐다.
이렇게 사용하게 될 경우 맞게 제거되지 않았다.
\W
를 사용하지 않고 범위를 이용하였다.
replaceAll("[^a-z0-9_.-]", "")
이렇게 작성하니 정규표현식이 맞게 적용이 되었다.
나머지 단계들을 문제없이 해결하였지만
"=.="
이라는 문자열이 들어갈 경우... 오류가 났다..
4단계는
if (new_id.charAt(0) == '.') new_id = new_id.substring(1);
if (new_id.charAt(new_id.length() - 1) == '.') new_id = new_id.substring(0, new_id.length() - 1);
이렇게 만들었다.
하지만 "=.="
이 들어갈 경우 "="
는 제거되고 "."
만 남는다.
여기서 "."
문자열의 길이는 1
.
if (new_id.charAt(new_id.length() - 1) == '.') new_id = new_id.substring(0, new_id.length() - 1);
에서
new_id = new_id.substring(0, new_id.length() - 1);
부분이 오류가 났다. 길이가 1
인 문자열일 때,
new_id = new_id.substring(0, 1 - 1); // new_id.substring(0, 0)
이렇게 된다.
substrin(0, 0)
는 할 수 없다. 0
번째부터 0
개를 자르는 것은 말이 안된다.
그래서
if (new_id.equals(".")) {
new_id = "";
}
을 추가하여 "."
일 때는 빈 배열로 만들어주었다.
첫 번째로 나오는 "."
는 제거해야하는 규칙이 있기 때문이다.
이렇게 반례를 해결하였다.
대문자와 소문자가 있는 배열이나, 문자열을 내림차순으로 정렬할 경우 자동으로 대문자가 더 큰 값으로 취급된다.
문제에 적용하지는 않았지만 에라토스테네스의 체의 원리(알고리즘)를 알게 되었다.
아예 몰라던 정규표현식을 어떨 때, 어떻게 사용하는지 조금 알게 되었다.
[]
: 범위표현 '-'
로 표현가능하다