이번주는 앞으로의 내가 나아가야할 방향성을 배운 날이라 생각한다.
취업을 위해 뭘 해야할지 몰랐던것이 문제라면 지금은 해야할것들이 보인다. 너무 잘보여서 문제이다. 매번 학습을 할때마다 나의 빈틈이보이고 알고리즘같은 경우는 디테일이 모잘라서 엣지케이스를 만나면 여지 없이 실패를 출력해낸다. 주변 동기들의 조언을 들어보면 많이 풀다보면, 익숙해지면 그런 것들이 서서히 보이기 시작한다고 한다. 내가 그 친구들에 비해서 얼마나 뒤늦게 출발했는가가 여실히 들어나는 예라고 생각이 들었다. 모자란 부분들을 채워나가고 더 많은 알고리즘 경험을 쌓자!
문제를 잘 풀진 못해도 뭘 해야할지 아는 달라진 내가 너무 좋다.
byte char
입력 스트림 InputStream Reader
출력 스트립 OuputStream Writer
노드 스트림
필터 스트림(Process Stream)
java.utill.Scanner
파일,입력 스트림등에서 데이터를읽어 구분자로 토큰화 하고 다양한 타입으로 형변환하여 리턴해주는 클래스
nextInt() , nextDouble(),next() → 구분자가 나오기 전까지 읽어 드린 후 다음에 진행 될때기존에 유효문자 전에 남아있는 구분자의 잔재를 다 떼버리고 다음 구분자 전까지의 유효문자만 출력한다 .
nextLine() →커서끝에서 부터 읽어온 후에 개행을 떼고 앞에온 개행을 떼고 출력 nextLine은 개행빼고 모두 유효글자이다.
code
public class IO2_ScannerTest {
public static void main(String[] args) {
String s1 = "안 \n녕 \n";
Scanner sc = new Scanner(s1);
System.out.print("읽은 문자열 :"+ sc.next());
System.out.print(",읽은 문자열 :"+ sc.next());
System.out.println("\n=================================");
String s2 = "안 녕 \n";
Scanner sc2 = new Scanner(s2);
System.out.print("읽은 문자열 :"+ sc2.nextLine());
System.out.println("\n=================================");
String s3 = "안 \n 녕 \n";
Scanner sc3 = new Scanner(s3);
System.out.print("읽은 문자열 :"+ sc3.nextLine());
System.out.println("\n=================================");
System.out.print("읽은 문자열 :"+ sc3.nextLine());
System.out.println("\n=================================");
}
}
출력
읽은 문자열 :안,읽은 문자열 :녕
읽은 문자열 :안 녕
읽은 문자열 :안
읽은 문자열 : 녕
NextLine과 나머지 3개는 섞어 쓸경우 이렇나 문제점을 잘 알고 진행해야한다.
대량의 데이터 처리 시 수행시간이 비효율적임
주요 메소드
버퍼를 이용해서 읽고 쓴느 함수, 이 함수는 버퍼를 이용하기 떄문에 이 함수를 이용하면 입출력의 효율이 굉장이 높아진다. 하드디스크의 경우 속도가 굉장히 느리기 때문에 키보드로 들어오는 입력은 시간이 굉장히 많이 걸리는 작업이다, 그래서 키보드가 입력을 받을 때마다 전송하는 것보다 중간에 버퍼를 만들어 데이터를 한데 묶어서 전송하는것이 효율적이다.
눈을 치울때 한자루식 퍼서 옮기는것보다 한번에 모아서 치우는것이 효율적이다.
system.in을 reader형으로 만들기 위해서 InputStreamReader를 사용하고 그 데이터를 BufferedRead의 데이터로 사용 한다.
구분자를 이용해 잘린 것들을 토큰이라고 부른다.
code
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class IO4_BufferedReaderTest {
public static void main(String[] args) throws NumberFormatException, IOException {
//파일에서 입력받을 경우
FileReader fr = new FileReader("BufferedReaderEx1.java");
BufferedReader br_f = new BufferedReader(fr);
//콘솔에서 입력받을 경우
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
//String 리턴값이라 형변환 필수! 라인단위 주로 테스트 케이스 갯수를 입력받을때 사용
int n = Integer.parseInt(in.readLine());
StringTokenizer st = new StringTokenizer(in.readLine(), " ");
for(int i=0;i<n;i++) {
System.out.println(st.nextToken());
}
for (int t = 1; t <= 10; t++) {
//int N값을 가져오는것 String타입이라서 Integer로 변환
N = Integer.parseInt(br.readLine().trim());
//toCharArray로 chars배열안에 읽어온 값들을 저장;
//Int로 사용 하고 싶다면 사용할떄 - '0'을 해주면됨
chars = br.readLine().toCharArray();
System.out.println(Arrays.toString(chars));
//배열에 삽입하는 두가지 방법
for (int i = 0; i < N; i++) {
nums_test[i]=Integer.parseInt(st.nextToken());
}
//2
nums=br.readLine().toCharArray();
}
}
}
Wrapper Class
기본 클래스를 참조클래스를 사용 (메소드)
int → Integer
double → Double
float → Float
boolean → Boolean
char → Character
parseInt → 문자열로 선언되어 있지만 숫자가 들어온 경우 int형으로 사용가능
StringBuilder
어떤 문제를 해결하기 위한 절차
직관과 체계적인 접근
체계적인 접근을 위한 질문들
비슷한 문제를 풀어본 적이 있던가 ?
문제를 단순화 할 수 있을까 ?
그림으로 그려 볼 수 있을까 ?
수식으로 표현 할 수 있을까 ?
문제를 분해 할 수 있을까 ? (→ 재귀)
뒤에서부터 생각해서 문제를 풀 수 있을까?
특정 형태의 답만 고려 할 수 있을까 ?
컴퓨터 프로그램을 실행 할 떄 이전에 계산한 값을 메모리에 저장해서 매번 다시 계산하지 않도록 전체적인 실행속도를 빠르게 하는 기술이다.
N개의 원판 이동 :
매번 실행 할때 마다 원판의 개수가 다르다. 시작 기둥과 목적기둥이 계속 바뀐다.
seudo code
//n개 원판을 시작기둥(from) -> 목적 기둥(to)으로 모두 이동
hanoi(n,from,temp,to)
honoi(n-1,from,to,temp)
//n번째원판 이동
hanoi(n-1,temp,from,to)
if(n==0) return; //기저조건
array of array
2차원 이상의 다차원 배열은 각 차원에 따라 크기를 명시한다.
행 우선 순회
열 우선 순회
지그재그 순회
행의 홀 ,짝으로 나누어서 처리하는 방법
짝수행 홀수행
0 +3 (3-0) 3
1 +1 (3-2) 2
2 -1 (3-4) 1
3 -3 (3-6) 0
일반식을 찾아서 해결 하는 방법 ( 생각이 안나면 시간낭비)
for (int i= 0 ; i< n;i++)
for(int j=0; j<m;j++)
{
array[i][j+(m-1)-2*j) * (i%2)]
}
지그재그 순회
for (int i = 0; i < row; i++) {
if(i%2==0) {
for (int j = 0; j < col; j++) {
//수행할일 행의 번호가 짝수일때 수행할일
}
}else
{
for (int j = col; j>=0; j++) {
//홀 수 일때 수행할일
}
}
}
델타를 이용한 2차열 배열 탐색
사방 탐색
dx ,dy를 배열로 만들어 사방 탐색을 접근
대신 상하좌우 따로 하는것 보다 실행 시간이 많이 걸릴 수도 있다
→ 데이터가 만을경우 따로 생성한느거 추천
전치행렬
탐욕적 알고리즘은 접근은 해답을 찾아내지 못하는 경우도 있으니 유의해야 한다.
완전 탐색 방법은 문제의 해법으로 생각할 수 있는 모든 경우의 수를 나열해보고 확인하는 기법
Brute-force 혹은 generate-and-test기법이라고도 불린다.
모든 경우의 수를 테스트한 후, 최종 해법을 도출한다.
구현시간은 빠르다
일반적으로 경우의 수가 상대적으로 작을때 유용하다.
완전 탐색의 예시 순열 조합 그리고 부분집합 과 같은 조합적 문제들과 연관된다
****순열 부분집합 조합은 매일 풀기
순열 문제의 경우 9! 10! 이 마지노선이라고 생각한다.
문제
code(지그재그탐색)
for (int i = 0; i < row; i++) {
if(i%2==0) {
for (int j = 0; j < col; j++) {
//수행할일 행의 번호가 짝수일때 수행할일
}
}else
{
for (int j = col; j>=0; j++) {
//홀 수 일때 수행할일
}
}
}
나열된 순서가 의미를 가지는 경우 → 대표 와 부대표를 뽑는 경우를 생각
서로 다른 것들 중 몇개를 뽑아서 한 줄로 나열하는 것
서로 다른 n개 중 r개를 택하는 순열은 아래와 같이 표현
→ nPr\
10! = 360만
3 P 3경우의 수 = n!과 같다.
반복문을 통한 순열 생성
재귀 호출을 통한 순열 생성
isSelected같은 중복 관리 필요 X
재귀호출을 이용한 조합 생성 알고리즘
code
집합에 포함된 원소들을 선택하는 것이다.
다수의 중요 알고리즘들이 원소의 그룹에서 최적의 부분 집합을 찾는 것이다.
예)배낭 짐싸기(Knapsack)
부분집합의 수
집합의 원소가 n개 일떄, 공집합을 포함한 부분집합 개수는 2^n개이다.
이는 각 원소를 부분집합에 포함시키거나 포함시키지 않는 2가지 경우를 모든 원소에 적용한 경우의 수와 같다.
원소의 개수가 몇개 안되는 경우 → 반복문으로 해결
원소의 개수를 모르거나 많은경우 → 재귀로 해결
탐욕 알고리즘은 최적해를 구하는데 사용되는 근시안적인 방법
여러 경우 중 하나를 결정해야 할 떄마다 그 순간에 최적이라고 생각 되는 것을 선택해 나가는 방식으로 진행하여 최종적인 해답에 도달한다.
각 선택의 시점에서 이루어지는 결정은 지역적으로는 최적이지만! 그선택들을 계속 수집하여 최종적인 해답을 만들었다고 하여 그것이 최적이라는 보장X
일반적으로 머리속에 떠오르는 생각을 검증 없이 바로 구현하면 Greedy적 접근이 된다
동작 과정
예제
거스름돈 줄이기
어떻게 하면 손님에게 거스름돈으로 주는 지폐와 동전의 개수를 최소한으로 줄일 수 있을까?
물건을 쌓아 올리듯 자료를 쌓아 올린 형태의 자료구조.
스택에 저장된 자료는 선형 구조를 갖는다.
선형구조 : 자료간의 관계가 1대 1의 관계를 갖는다.
비선형구조: 자료간의 관계가 1대 N의 관계를 갖는다. (예 : 트리)
스택에 자료를 삽입하거나 스택에서 자료를 꺼낼 수 있다.
후입선출구조(LIFO,Last-In-First-Out)
마지막에 넣은 자료가 제일 먼저 나온다.
주요연산
push : 저장소에 자료를 저장한다 (삽입)
pop : 저장소에 자료를 꺼낸다. (삭제), 꺼낸 자료는 삽입한 자료의 역순으로 꺼낸다.
peek : 스택의 top에 있는 item(원소)를 반환한다.
java.utill.Stack
주요 메소드
push() 삽입
pop() 삭제
isEmpty()
size()
스택의 활용
스택을 이용한 괄호 검사
Function call
프로그램에서의 함수 호출과복귀에 따른 수행 순서를 관리 , 가장 마지막에 호출된 함수가 가장 먼저 실행을 완료하고 복귀하는 후입선출 구조이므로, 후입선출 구조의 스택을 이용하여 수행순서 관리
스택과 마찬가지로 삽입과 삭제의 위치가 제한적인 자료구조
큐의 뒤에서는 삽입만 하고, 큐의 앞에서는 삭제만 이루어지는 구조
선입선출구조 (FIFO : First In First Out)
큐에 삽입한 순서대로 원소가 저장되어, 가장 먼저 삽입(First In)된 원소는 가장 먼저 삭제(First Out) 된다.
Front는 직전에 나간 것을 가리키고 있는곳
Rear 는 마지막에 저장된 원소를 가리키고 있다.
큐의 기본 연산
enQueue(A)
deQueue(B)
Java에서의 큐
java.utill.Queue
큐에 필요한 연산을 선언해 놓은 인터페이스 (명세,약속)→ 즉 사용방법만 존재.
LinkedList클래스를 queue 인터페이스의 구현체로 많이 사용됨!
LinkedList는 Queue 성질을 가지고 있는것이지 Queue만 구현한것이 아니다. 메소드 사용에 주의할것
주요 메소드
offer() → 삽입 , EnQueue
poll() → 삭제 , DeQueue
isEmpty()
size()