
문자열의 길이를 측정하는 문법
특정 인덱스 접근하는 문법
(Int)str
| 항목 | String | char |
|---|---|---|
| 자료형 | 문자열 (문자 여러 개) | 문자 하나 |
| 표현 예시 | "hello" | 'h' |
| 메모리 구조 | 객체 (Heap에 저장됨) | 기본형 (Stack에 저장됨) |
| 저장하는 값 | 0글자 이상 문자들의 조합 | 문자 1개만 저장 가능 |
| 입력 방법 | sc.next() 또는 sc.nextLine() | sc.next().charAt(0) |
| 길이 확인 | str.length() → 문자 수 | 항상 1 (단일 문자) |
| 비교 방법 | str.equals("hello") | ch == 'h' |
| 아스키코드 출력 | System.out.println((int) str.charAt(0)) | System.out.println((int) ch) |
| 기본값 (초기화) | null | '\u0000' (널 문자) |
Stream안에 요소들을 오름차순 또는 지정한 기준대로 정렬하는 중간 연산자
스트림의 요소들을 특정 기준(키)으로 그룹화해서 Map<기준, List<요소>> 형식으로 묶어줌
그룹화된 각 항목의 개수를 셈 (기본적으로 .size()와 비슷한 역할을 대신함)
N개의 숫자가 공백 없이 쓰여있다. 이 숫자를 모두 합해서 출력하는 프로그램을 작성하시오.
첫째 줄에 숫자의 개수 N (1 ≤ N ≤ 100)이 주어진다. 둘째 줄에 숫자 N개가 공백없이 주어진다.
입력으로 주어진 숫자 N개의 합을 출력한다.
1
1
1
5
54321
15
25
7000000000000000000000000
7
11
10987654321
46
package string;
import java.util.Scanner;
public class BOJ_DigitSumCalculator {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
String s = sc.next();
int sum = 0;
for(int i=0;i<n;i++){
sum += s.charAt(i) - '0';
}
System.out.print(sum);
}
}
문자열로 입력된 숫자를 하나씩 분리하여 합산하는 연습. char → int 변환 (char - '0')개념을 익히기 위한 문제.
알파벳 소문자로만 이루어진 단어 S가 주어진다. 각각의 알파벳에 대해서, 단어에 포함되어 있는 경우에는 처음 등장하는 위치를, 포함되어 있지 않은 경우에는 -1을 출력하는 프로그램을 작성하시오.
첫째 줄에 단어 S가 주어진다. 단어의 길이는 100을 넘지 않으며, 알파벳 소문자로만 이루어져 있다.
각각의 알파벳에 대해서, a가 처음 등장하는 위치, b가 처음 등장하는 위치, ... z가 처음 등장하는 위치를 공백으로 구분해서 출력한다.
만약, 어떤 알파벳이 단어에 포함되어 있지 않다면 -1을 출력한다. 단어의 첫 번째 글자는 0번째 위치이고, 두 번째 글자는 1번째 위치이다.
baekjoon
1 0 -1 -1 2 -1 -1 -1 -1 4 3 -1 -1 7 5 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
package string;
import java.util.Arrays;
import java.util.Scanner;
public class BOJ_10809_AlphabetPositionFinder {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String s = sc.nextLine();
int [] arr = new int[26];
Arrays.fill(arr,-1);
for(int i=0;i<s.length();i++){
char ch = s.charAt(i);
int idx = ch - 'a';
if(arr[idx]==-1){
arr[idx]=i;
}
for(int alp :arr){
System.out.print(alp+" ");
}
}
}
}
array를 채워주는 문법
알파벳 a~z의 최초 등장 위치를 기록하는 배열 활용 문제. char - 'a'로 인덱스 매핑, Arrays.fill()로 초기화
문자열 S를 입력받은 후에, 각 문자를 R번 반복해 새 문자열 P를 만든 후 출력하는 프로그램을 작성하시오. 즉, 첫 번째 문자를 R번 반복하고, 두 번째 문자를 R번 반복하는 식으로 P를 만들면 된다. S에는 QR Code "alphanumeric" 문자만 들어있다.
QR Code "alphanumeric" 문자는 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ$%*+-./: 이다.
첫째 줄에 테스트 케이스의 개수 T(1 ≤ T ≤ 1,000)가 주어진다. 각 테스트 케이스는 반복 횟수 R(1 ≤ R ≤ 8), 문자열 S가 공백으로 구분되어 주어진다. S의 길이는 적어도 1이며, 20글자를 넘지 않는다.
각 테스트 케이스에 대해 P를 출력한다.
2
3 ABC
5 /HTP
AAABBBCCC
/////HHHHHTTTTTPPPPP
package string;
import java.util.Scanner;
public class BOJ_2675_StringRepeater {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int t = sc.nextInt();
for (int i = 0; i < t; i++) {
int r = sc.nextInt();
String s = sc.next();
String answer = "";
for(int j=0;j<s.length();j++){
char ch = s.charAt(j);
for(int k=0;k<r;k++){
answer += ch;
}
}
System.out.println(answer);
}
}
}
각 문자를 정해진 횟수만큼 반복 출력. 중첩 반복문과 문자 처리, 그리고 입출력 형식 조작을 익히게 하기 위한 기본적인 문자열 처리 문제
정렬 알고리즘은 정렬되지 않은 배열이 주어졌을 때, 어떻게 오름차순으로 정렬할 수 있을까?를 해결 하는 알고리즘
그중에 매우 기본적인 알고리즘인 버블정렬은 첫번재와 두번를 비교함 왼쪽이 오른쪽보다 크면 교환(swap)함
그리고 두번째와 3번째를 비교함 이걸 계속 반복함 그걸 패스쓰루라고함 더이상 반복하지 않으면 정렬이 끝남
버블 정렬 알고리즘에 포함된 단계는 2종류임 비교 와 교환(swap)
비교는 원소 N개가 있을때 (N-1) + (N-2) + (N-3)… 번의 단계가 필요함
최악의 시나리오의 경우교환(swap)도 똑같은 단계가 필요함
따라서 버블 정렬은 원소 N개가 있을때 N^2번의 단계가 필요하고
빅오 표기법은 버블 정렬의 효율성을 O(N^2)라고 하고 이를 이차 시간이라고도 부름
배열에서 중복 값이 있는지 확인하는 애플리케이션을 작성한다고 하면 for문 중첩으로 루프를 돌리는게 제일 먼저 떠오름
Function hasDuplicateValue(array){
for(various I =0;i<array.length;i++){
for(var j =0;j<array.length;j++){
f(I!=just && array[I] == array[j]){
Return true;}
}
}
}
하지만 이 구조를 빅 오로 표기하면 N^2의 알고리즘을 가짐 이는 상대적으로 느린 알고리즘임
이를 해결하기 위해서 중첩루프를 쓰지 않는 함수를 구현해 볼 수 있음 이는 O(N)임
결과적으로 O(N^2)보다 )O(N)이 훨씬 빠르므로 두번째 접근법을 사용하여 최적하는게 좋음
많은 데이터를 처리할수록 차이가 더 클 것임
Function hasDuplicateValue(array){
Var existingNumber = [];
for(var I = 0 ; I<array.length;i++){
if(existingNumbers[array[I] === undefined]){
existingNumbers[array[I]] = 1;
}else{
return true;
}
}
return false;
}
빅오 표기법을 이해하면 느린코드를 식별하고 더 빠른 알고리즘을 골라낼 수 있음
Key Value 형태로 데이터를 저장하는 자료구조
빠르게 찾고 싶을때 사용함 O(1)중복 key 불가능 함
아이디 찾기 , 캐시, 카운팅에 주로 사용됨
Map<String, Integer> map = new HashMap<>();
map.put("apple", 1);
map.get("apple"); // 결과: 1
계층적 구조의 노드기반 자료구조
루트 - 자식 노드 형태로 뻗어감 중복 안됨
BST기준 O(logN)
정렬된 자료보관, 탐색 트리 에 사용됨
종류 설명
이진 트리 자식이 최대 2개
이진 탐색 트리(BST) 왼쪽 < 부모 < 오른쪽
힙(Heap) 최대값/최소값 빠르게 꺼내는 용도
트라이(Trie) 문자열 검색, 자동완성용
AVL, 레드블랙 트리 자동 균형 잡는 BST (실무에서 많이 씀)
HyperTextTransferProtocol
클라이언트(브라우저,앱)와 서버가 서로 데이터를 주고받기 위한 약속된 통신 규칙
클라이언트 -> 요청(Request) -> 서버
서버 -> 응답(Response) -> 클라이언트
GET /todos HTTP/1.1 // 요청라인 : 메서드 + 경로 + 버전
Host: example.com
User-Agent: Chrome/...
Content-Type: application/json //헤더 : 부가정보
(빈 줄) // 본문과 헤더 구분
{"task":"청소하기","done":false} // 바디 :실제데이터
HTTP/1.1 200 OK // 상태라인 : 버전+상태 코드 + 메세지
Content-Type: application/json //헤더 부가 정보
Content-Length: 37
(빈 줄) // 본문과 헤더 구분
{"id":1,"task":"청소하기","done":false} //바디 :응답 데이터
| 메서드 | 설명 | REST 예시 |
|---|---|---|
| GET | 데이터 조회 | GET /todos |
| POST | 새 데이터 생성 | POST /todos |
| PUT | 데이터 전체 수정 | PUT /todos/1 |
| PATCH | 데이터 일부 수정 | PATCH /todos/1 |
| DELETE | 삭제 | DELETE /todos/1 |
| 코드 | 의미 | 예시 |
|---|---|---|
| 200 OK | 성공 | 요청 정상 처리 |
| 201 Created | 생성됨 | POST 성공 시 |
| 400 Bad Request | 잘못된 요청 | 파라미터 오류 |
| 401 Unauthorized | 인증 실패 | 로그인 필요 |
| 403 Forbidden | 접근 금지 | 권한 없음 |
| 404 Not Found | 없는 자원 | 잘못된 URL |
| 500 Internal Server Error | 서버 에러 | 코드 오류 발생 시 |
REpresentational State TransferApplication Programming Interface
HTTP 기반으로 동작하는
규칙이 정해진 방식의 URL과 메서드 설계
클라이언트가 자원(Resource) 에 요청(Request) 을 보내고, 서버가 응답(Response) 하는 구조
자원 : 데이터의 대상 (/todos,users/1)
행위 : 어떤 동작인지 (GET,POST,PUT,DELETE)
표현 : 주고받는 데이터 형식 ( Json,Xml등)
uri는 자원을 표현함 /todos,/todos/1 동사는 안씀 /getTodo,/addTodo
HTTP 메소드로 행위를 구분함 GET,POST,PUT,DELETE
요청 간 서버가 상태 저장을 하지 않음
일관된 구조를 사용함
우리가 사용하는 자원은 Todo
Json 으로 되어있고
Id,Task,Dudate,Done 가 있음
| 기능 | HTTP Method | URI | 설명 |
|---|---|---|---|
| 할 일 전체 조회 | GET | /todos | 전체 목록 가져오기 |
| 특정 할 일 조회 | GET | /todos/{id} | ID로 단일 조회 |
| 할 일 추가 | POST | /todos | 새 할 일 생성 |
| 할 일 수정 | PUT | /todos/{id} | 전체 수정 |
| 완료 체크 | PATCH | /todos/{id}/done | 완료 처리 (부분 수정) |
| 할 일 삭제 | DELETE | /todos/{id} | 삭제 |
**전체 흐름을 먼저 잡고 필요한 메서드는 나중에 만드는 탑다운 방식 사용
새로운 브랜치 생성 refactor/RESTAPI
API사용하기위한 기본 틀 생성
API는 요청이들어오면 응답을 해야되기 때문에
String을 사용함
| 기능 | HTTP Method | URI | 설명 |
|---|---|---|---|
| 할 일 전체 조회 | GET | /todos | 전체 목록 가져오기 |
| 특정 할 일 조회 | GET | /todos/{id} | ID로 단일 조회 |
| 할 일 추가 | POST | /todos | 새 할 일 생성 |
| 할 일 수정 | PUT | /todos/{id} | 전체 수정 |
| 완료 체크 | PATCH | /todos/{id}/done | 완료 처리 (부분 수정) |
| 할 일 삭제 | DELETE | /todos/{id} | 삭제 |
특정 할일 조회와 수정같은 url에 id가 함께 입력되는 부분에서 id를 빼내기 위해
Main에서 호출할때
Method 와 url필요
입력시 오류 발생을 막기위해 띄어씌기를 없애는 trim사용
public class TodoController {
private final TodoService service;
public TodoController(TodoService service){
this.service = service;
}
private int extractId(String uri) {
try {
String[] parts = uri.split("/");
return Integer.parseInt(parts[2]);
} catch (Exception e) {
return -1;
}
}
public String handleRequest(String method,String url){
if(method.equals("GET")&&url.equals("/todos")){
return service.getAllTodos();
} else if(method.equals("POST")&&url.equals("/todos")){
return service.createTodo();
} else if(method.equals("GET")&&url.startsWith("/todos/")){
int id = extractId(url);
return service.getTodoById(id);
} else if(method.equals("PUT")&&url.startsWith("/todos/")){
int id = extractId(url);
return service.updateTodo(id);
} else if(method.equals("PATCH")&&url.startsWith("/todos/")&&url.endsWith("/done")){
int id = extractId(url);
return service.markDone(id);
} else if(method.equals("DELETE")&&url.startsWith("/todos/")){
int id = extractId(url);
return service.deleteTodo(id);
}
return "404 Not Found";
}
}
public class TodoService {
public String getAllTodos() {
return "[{ \"id\": 1, \"task\": \"공부하기\", \"done\": false }]";
}
public String createTodo() {
return "새로운 할 일이 생성되었습니다.";
}
public String getTodoById(int id) {
return "ID " + id + "번 할 일 조회";
}
public String updateTodo(int id) {
return "ID " + id + "번 할 일 수정 완료";
}
public String markDone(int id) {
return "ID " + id + "번 할 일 완료 처리됨";
}
public String deleteTodo(int id) {
return "ID " + id + "번 할 일 삭제됨";
}
}
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
TodoService service = new TodoService();
TodoController controller = new TodoController(service);
System.out.println(" 무슨 일을 하실건가요?");
System.out.println("ex): POST /todos");
while (true) {
System.out.print("\n>> ");
String method = sc.next();
String uri = sc.nextLine().trim();
String response = controller.handleRequest(method, uri);
System.out.println("📦 응답: " + response);
}
}
}
정신을 차리고 다시 열심히 해보겠습니다
저번주에 N2시험을 봐야되서 잠시 일본어에 집중을 했습니다 ( 사실 좀 많이 놀았음 )
드디어 RESTFUL API에 손을 대기 시작했습니다 url과 메소드에 뭘 하는지 다 나와있어서
한눈에 보기도 편하고 Sprig가기전 마지막 연습겸 하고있습니다
자료구조 책을 보면서 빅오 표기법이라는걸 알게되고 중첩문은 단계가 많이 걸리는구나 등
알고리즘의 효율성에대해 더 생각하게 되었습니다
이제 우테코 지원까지 2달 최선을 다하겠습니다!