250822
- 다단계칫솔판매 ok - 시간날 때 객체지향으로 변환, 포스팅
- 행렬의덧셈 ok
- 최댓값과 최솟값 ok
- 직사각형 별찍기 ok 포스팅 - 이중for문 입력순서, repeat
- 최솟값 만들기 ok - 포스팅 - 그리디
- JadenCase 문자열 만들기 ok - 포스팅 split 메서드의 한계
- 이진 변환 반복하기 푸는 중
- 크기가 작은 부분 문자열 ok - 포스팅 compareTo메서드, 길이 주의사항
노트북에 크롬, 인텔리제이, 이클립스, VSCode, WSL(리눅스) 환경 세팅 + 스티커 붙이기
빛가람 도서관 2권 반납 + 1권 연장 ok
크기가 작은 부분 문자열
첫번째 시도
class Solution {
public int solution(String t, String p) {
int len = p.length();
int count = 0;
for(int i = 0; i < t.length() - len; i++) {
long subNum = Long.parseLong(t.substring(i, i + len));
long pNum = Long.parseLong(p);
if (subNum < pNum) {
count++;
};
}
return count;
}
}
틀린 이유
1. 루프 범위 문제
for(int i = 0; i < t.length() - len; i++)
- 이렇게 하면 마지막 부분 문자열을 검사하지 못함.
- <= 로 바꿔야 마지막 부분 문자열까지 검사 가능
2. 비교 연산 문제
if (subNum < pNum)
- 문제에서는 부분 문자열 <= p 인 경우도 세야 한다.
- 그런데 < 만 쓰면 같은 값(subNum == pNum) 은 카운트되지 않는다.
- <= 로 바꿔야 마지막 부분 문자열까지 카운팅 가능
if (subNum <= pNum)
3. 반복문 안에서 pNum 계속 변환
long pNum = Long.parseLong(p);
- 매 반복마다 변환하고 있음 → 불필요하게 반복 연산
- 반복문 밖에서 한 번만 변환하도록 위치를 for문 위쪽으로 변경했다.
두번째시도 (정답코드)
class Solution {
public int solution(String t, String p) {
int len = p.length();
int count = 0;
long pNum = Long.parseLong(p);
for(int i = 0; i <= t.length() - len; i++) {
long subNum = Long.parseLong(t.substring(i, i + len));
if (subNum <= pNum) {
count++;
};
}
return count;
}
}
개선한 코드
class Solution {
public int solution(String t, String p) {
int len = p.length();
int count = 0;
for (int i = 0; i <= t.length() - len; i++) {
String sub = t.substring(i, i + len); // 부분 문자열
if (sub.compareTo(p) <= 0) { // 문자열 끼리 비교
count++;
}
}
return count;
}
}
부분 문자열 길이를 p와 같게 맞춘 뒤 compareTo 사용하면 숫자 문자열 비교 가능
1. compareTo 메서드
자바에서 String.compareTo(String other)
는 문자열 사전식 비교를 해주는 메서드이다.
- 반환값:
- 0 → 두 문자열이 같음
- 양수 → 첫 문자열이 사전상 더 뒤에 있음
- 음수 → 첫 문자열이 사전상 더 앞에 있음
즉,
"abc".compareTo("abd") // 결과: -1 ("abc"가 앞)
"abc".compareTo("abc") // 결과: 0
"abd".compareTo("abc") // 결과: 1 ("abd"가 뒤)
2. 숫자로만 이루어진 문자열에도 적용가능하다. 이 때 길이가 중요하다.
- 길이가 같으면 사전식 비교 = 숫자 비교 와 같음
"123".compareTo("234") // 음수 → "123" < "234"
"456".compareTo("456") // 0 → 같음
"789".compareTo("123") // 양수 → "789" > "123"
- 중요: 길이가 다르면 사전식 비교라서 작은 자리수부터 비교됨
- 숫자 비교와 같지 않음 → 항상 길이가 같아야 안전하다
예: "99".compareTo("100") → 결과: 양수 ('9' > '1' 비교)
JadenCase 문자열 만들기
첫번째시도
class Solution {
public String solution(String s) {
StringBuilder sb = new StringBuilder();
String[] str = s.split(" ");
for (int i = 0; i < str.length; i++) {
char first = str[i].charAt(0);
// 첫 번째 문자가 숫자인지 확인
if (Character.isDigit(first)) {
sb.append(first); // 숫자면 그대로 StringBuilder에 추가
} else {
sb.append(Character.toUpperCase(first)); // 숫자가 아니라면 대문자로 전환
}
if (str[i].length() > 1) {
sb.append(str[i].substring(1).toLowerCase()); // 1번 인덱스부터 잘라서 소문자로 전환 후 추가
sb.append(" "); // 공백 추가
}
}
return sb.toString().trim(); // 마지막 공백 제거
}
}

틀린 이유 & 수정 사항
- "공백문자가 연속해서 나올 수 있습니다" 처리 추가해서 수정
두번째 시도
class Solution {
public String solution(String s) {
StringBuilder sb = new StringBuilder();
String[] str = s.split(" ", -1);
for (int i = 0; i < str.length; i++) {
if(str[i].length() == 0) { // 여기서 처리 str[i].equals(" ") 도 됨
sb.append(" ");
continue;
}
char first = str[i].charAt(0);
if (Character.isDigit(first)) {
sb.append(first);
} else {
sb.append(Character.toUpperCase(first));
}
if (str[i].length() > 1) {
sb.append(str[i].substring(1).toLowerCase());
sb.append(" ");
}
}
return sb.toString().trim();
}
}
틀린 이유 & 수정 사항
trim()
제거 → 원본 문자열 끝 공백 보존if (i < str.length - 1) sb.append(" ");
→ 마지막 단어 뒤에는 불필요한 공백 안 넣고, 중간에는 넣도록 if문 두 개로 나눔
세 번째 시도
class Solution {
public String solution(String s) {
StringBuilder sb = new StringBuilder();
String[] str = s.split(" ", -1);
for (int i = 0; i < str.length; i++) {
if(str[i].length() == 0) {
sb.append(" ");
continue;
}
char first = str[i].charAt(0);
if (Character.isDigit(first)) {
sb.append(first);
} else {
sb.append(Character.toUpperCase(first));
}
if (str[i].length() > 1) {
sb.append(str[i].substring(1).toLowerCase());
}
if (i < str.length - 1) {
sb.append(" ");
}
}
return sb.toString();
}
}
계속 8번케이스만 오류남
틀린 이유
- split()메서드의 한계
- 문자열 끝에 공백이 여러 개 있으면
split(" ", -1)
이든split(" ", 0)
이든 결과에 빈 문자열 여러 개가 붙는다. - 즉, 단어 사이 연속 공백 처리는 가능하다. 중간 공백은 배열 안 빈 문자열로 잡아서 " " 처리 가능하기 때문이다.
- 하지만 끝 공백이나 split로 쪼갤 수 없는 일부 공백은 반영되지 않는다. 즉, split 기반 코드로는 끝 공백 처리 불가
- 프로그래머스 JadenCase 문제에서는 입력 그대로 공백 유지가 필수이므로, split 방식으로는 항상 일부 반례에서 틀림
반례
// " for the what 1what " 같은 입력을 split하면
["", "", "for", "the", "what", "1what"]
입력값 〉 " for the what 1what "
기댓값 〉 " For The What 1what "
내코드 〉 " For The What 1what" (끝 공백 없음)
네 번째 시도 (정답코드)
class Solution {
public String solution(String s) {
StringBuilder sb = new StringBuilder();
String[] str = s.split(" ", 0); // split 사용, 마지막 빈 문자열 제외
for (int i = 0; i < str.length; i++) {
if (str[i].equals("")) {
sb.append(" ");
continue;
}
char first = str[i].charAt(0);
if (Character.isDigit(first)) {
sb.append(first);
} else {
sb.append(Character.toUpperCase(first));
}
if (str[i].length() > 1) {
sb.append(str[i].substring(1).toLowerCase());
}
if (i < str.length - 1) {
sb.append(" ");
}
}
// 원본 문자열 끝 공백 유지
int originalLength = s.length();
while (sb.length() < originalLength) {
sb.append(" ");
}
return sb.toString();
}
}
- split으로 단어 처리 → 단어 첫 글자 대문자, 나머지 소문자, 숫자 처리
- 배열 안 빈 문자열 →
" "
로 처리 → 연속 공백 유지 - 반복 끝난 후 sb 길이 < 원본 문자열 길이이면, 부족한 공백 추가 → 끝 공백 유지
개선한 코드 - split() 사용하지 않고, 문자열을 처음부터 끝까지 순회하면서 처리하는 방법이 가장 안전함.
class Solution {
public String solution(String s) {
StringBuilder sb = new StringBuilder();
boolean isFirst = true; // 단어 첫 글자인지 여부
for (char c : s.toCharArray()) {
if (c == ' ') {
sb.append(c);
isFirst = true; // 다음 글자는 단어 첫 글자
} else {
if (isFirst) {
sb.append(Character.isLetter(c) ? Character.toUpperCase(c) : c);
isFirst = false;
} else {
sb.append(Character.toLowerCase(c));
}
}
}
return sb.toString();
}
}
- 연속 공백 → 그대로 유지
- 숫자로 시작하는 단어 → 그대로 처리
- 끝 공백 → 그대로 유지
- split 때문에 발생하는 마지막 공백 누락 문제 완전히 해결
최솟값 만들기
- A를 오름차순 B를 내림차순으로 정렬해서
- 같은 인덱스끼리 곱하면 항상 최소 합을 보장한다
- 와이? 작은 수는 큰 수와 곱하는게 항상 더 유리하다
import java.util.*;
class Solution
{
public int solution(int []A, int []B) {
int answer = 0;
Arrays.sort(A);
Arrays.sort(B);
for (int i = 0; i < A.length; i++) {
answer += A[i] * B[B.length - 1 - i];
}
return answer;
}
}
최댓값과 최솟값
- Arrays.sort()로 음수값 포함된 숫자 정렬하면 안됨
- Arrays.sort(String[])은 사전순(lexicographical order) 정렬
- 즉, 첫번째 문자부터 유니코드(ASCII)값 기준으로 비교한다.
- 첫 글자가 '-' → 아스키코드 45
- 두 번째 글자는 '1'은 49, '4'는 52라서
- 비교걸과 '1'(49) < '4'(52)라서 -1이 -4보다 앞에 옴
import java.util.Arrays;
class Solution {
public String solution(String s) {
String[] str = s.split(" ");
int[] nums = new int[str.length];
for (int i = 0; i < str.length; i++) {
nums[i] = Integer.parseInt(str[i]);
}
Arrays.sort(nums);
return nums[0] + " " + nums[nums.length - 1];
}
}
- split(" ") → 공백으로 나누기
- 문자열을 숫자로 변환한 후 정렬
- 숫자 배열 정렬
- 최소값 최대값 반환
직사각형 별찍기
import java.util.Scanner;
class Solution {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt(); // 가로
int m = sc.nextInt(); // 세로
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
System.out.print("*");
}
System.out.println();
}
}
}
repeat
import java.util.Scanner;
class Solution {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt(); // 가로
int m = sc.nextInt(); // 세로
String line = "*".repeat(n);
for (int i = 0; i < m; i++) {
System.out.println(line);
}
sc.close();
}
}
행렬의 덧셈
import java.util.Arrays;
class Solution {
public int[][] solution(int[][] arr1, int[][] arr2) {
int[][] answer = new int[arr1.length][arr1[0].length];
for (int i = 0; i < arr1.length; i++) {
for (int j = 0; j < arr1[0].length; j++) {
answer[i][j] = arr1[i][j] + arr2[i][j];
}
}
return answer;
}
}