no image
[프로그래머스]게임 맵 최단거리
문제 ROR 게임은 두 팀으로 나누어서 진행하며, 상대 팀 진영을 먼저 파괴하면 이기는 게임입니다. 따라서, 각 팀은 상대 팀 진영에 최대한 빨리 도착하는 것이 유리합니다. 지금부터 당신은 한 팀의 팀원이 되어 게임을 진행하려고 합니다. 다음은 5 x 5 크기의 맵에, 당신의 캐릭터가 (행: 1, 열: 1) 위치에 있고, 상대 팀 진영은 (행: 5, 열: 5) 위치에 있는 경우의 예시입니다. 위 그림에서 검은색 부분은 벽으로 막혀있어 갈 수 없는 길이며, 흰색 부분은 갈 수 있는 길입니다. 캐릭터가 움직일 때는 동, 서, 남, 북 방향으로 한 칸씩 이동하며, 게임 맵을 벗어난 길은 갈 수 없습니다. 아래 예시는 캐릭터가 상대 팀 진영으로 가는 두 가지 방법을 나타내고 있습니다. 첫 번째 방법은 11개의 ..
2021.10.21
[프로그래머스]표 편집
https://programmers.co.kr/learn/courses/30/lessons/81303 코딩테스트 연습 - 표 편집 8 2 ["D 2","C","U 3","C","D 4","C","U 2","Z","Z"] "OOOOXOOO" 8 2 ["D 2","C","U 3","C","D 4","C","U 2","Z","Z","U 1","C"] "OOXOXOOO" programmers.co.kr 문제 "U X": 현재 선택된 행에서 X칸 위에 있는 행을 선택합니다. "D X": 현재 선택된 행에서 X칸 아래에 있는 행을 선택합니다. "C" : 현재 선택된 행을 삭제한 후, 바로 아래 행을 선택합니다. 단, 삭제된 행이 가장 마지막 행인 경우 바로 윗 행을 선택합니다. "Z" : 가장 최근에 삭제된 행을 ..
2021.10.21
no image
[Server]운영 서버에 대한 정리
🪙운영서버 운영 서버는 개발이나 테스트 목적이 아닌 실제 사용자들을 대상으로 서비스하는 서버를 의미한다. 테스트 목적의 서버라면 많은 요청이 발생할 일도 없고 장애가 발생하더라도 금전적인 문제나 큰 문제가 발생하지 않는다. 하지만 운영 서버는 테스트 목적의 서버와는 다르게 트래픽 대응도 해야 하고 빠은 응답 속도와 높은 가용성을 보장해야 한다. 그러기 위해서는 운영 서버는 테스트 서버와 다르게 다양한 구성 요소를 포함해야 한다. 운영 서버 관리에는 세 단계가 있다. 운영 서버 관리는 크게 '환경 구성' , '코드 배포' , '모니터링'으로 나뉜다. 환경 구성은 서비스할 코드를 구동시킬 수 있는 서버 인프라를 구축하는 것이다. 코드 배포는 환경 구성 과정에서 구성한 최신 버전의 코드를 빠르고 안전하게 배포..
2021.10.21
no image
[프로그래머스]쿼드 압축 후 개수세기(JAVA)
문제 설명 0과 1로 이루어진 2n x 2n 크기의 2차원 정수 배열 arr이 있습니다. 당신은 이 arr을 쿼드 트리와 같은 방식으로 압축하고자 합니다. 구체적인 방식은 다음과 같습니다. 당신이 압축하고자 하는 특정 영역을 S라고 정의합니다. 만약 S 내부에 있는 모든 수가 같은 값이라면, S를 해당 수 하나로 압축시킵니다. 그렇지 않다면, S를 정확히 4개의 균일한 정사각형 영역(입출력 예를 참고해주시기 바랍니다.)으로 쪼갠 뒤, 각 정사각형 영역에 대해 같은 방식의 압축을 시도합니다. arr이 매개변수로 주어집니다. 위와 같은 방식으로 arr을 압축했을 때, 배열에 최종적으로 남는 0의 개수와 1의 개수를 배열에 담아서 return 하도록 solution 함수를 완성해주세요. 제한사항 arr의 행의..
2021.10.19
no image
[프로그래머스] 배달
문제 설명N개의 마을로 이루어진 나라가 있습니다. 이 나라의 각 마을에는 1부터 N까지의 번호가 각각 하나씩 부여되어 있습니다. 각 마을은 양방향으로 통행할 수 있는 도로로 연결되어 있는데, 서로 다른 마을 간에 이동할 때는 이 도로를 지나야 합니다. 도로를 지날 때 걸리는 시간은 도로별로 다릅니다. 현재 1번 마을에 있는 음식점에서 각 마을로 음식 배달을 하려고 합니다. 각 마을로부터 음식 주문을 받으려고 하는데, N개의 마을 중에서 K 시간 이하로 배달이 가능한 마을에서만 주문을 받으려고 합니다. 다음은 N = 5, K = 3인 경우의 예시입니다.위 그림에서 1번 마을에 있는 음식점은 [1, 2, 4, 5] 번 마을까지는 3 이하의 시간에 배달할 수 있습니다. 그러나 3번 마을까지는 3시간 이내로 배..
2021.10.18
no image
[JPA]Fetch.Lazy를 설정했을때 @OneToOne에서 발생하는 이슈
JPA는 개발하는 입장에서 매우 편리하고 설정만 잘하면 편할거라고 생각하는데 사용하기 편하고 쉬운만큼 성능적인 측면에서 생각하지 못한 이슈가 발생할 수 있다.이번에 정리할 이슈는 즉시로딩(EAGER Loading)과 지연로딩(LAZY Loading)이다. @OneToOne 매핑시에 지연로딩(LAZY Loading)로 설정해도 즉시로딩(EAGER Loading)로 작동하는 경우가 있다.이번 포스팅에서는 발생하는 이슈에 대해서 해결책을 적어보려한다. 일단 정상적으로 작동하는 예제이다. 일대일 단방향 매핑으로 외래키를 가지고 있는 USER가 연관관계 주인이다. 여기서 유저를 조회하면 어떻게 쿼리가 작동하는지 보자 이처럼 이름으로 조회하면 select user0_.user_id as user_id1_1_, us..
2021.10.13
no image
[프로그래머스]모음 사전(JAVA)
문제가 까다로워 보여도 점화식만 찾으면 쉽게 풀수있다. 풀이 5번째 자리 수는 AEIOU 순서대로 바뀔때 1씩 증가한다. =14번째 자리 수는 AEIOU 순서대로 바뀔때 5씩 증가하지만 5번째자리에 숫자가 없는 경우를 더해 +1해서 6씩 증가한다. = 63번째 자리 수는 AEIOU 순서대로 바뀔때 4번째 자리 수 증가율 *3번째 자리 수 증가율+3번째 자리까지만 있는 경우(6 *5 +1 )씩 증가한다. =312번째 자리 수는 AEIOU 순서대로 바뀔때 3번째 자리 수 증가율 (31)* 2번째 자리 수 증가율(5) +2번째 자리까지만 있는 경우(+1) 씩 증가한다 식은 (31*5+1) .= 1561번째 자리 수는 AEIOU 순서대로 바뀔때 2번째 자리 수 증가율 (156)* 1번째 자리 수 증가율(5) +..
2021.10.12
no image
[프로그래머스]프렌즈 4블록(JAVA)
문제블라인드 공채를 통과한 신입 사원 라이언은 신규 게임 개발 업무를 맡게 되었다. 이번에 출시할 게임 제목은 "프렌즈4블록".같은 모양의 카카오프렌즈 블록이 2×2 형태로 4개가 붙어있을 경우 사라지면서 점수를 얻는 게임이다.만약 판이 위와 같이 주어질 경우, 라이언이 2×2로 배치된 7개 블록과 콘이 2×2로 배치된 4개 블록이 지워진다. 같은 블록은 여러 2×2에 포함될 수 있으며, 지워지는 조건에 만족하는 2×2 모양이 여러 개 있다면 한꺼번에 지워진다.블록이 지워진 후에 위에 있는 블록이 아래로 떨어져 빈 공간을 채우게 된다.만약 빈 공간을 채운 후에 다시 2×2 형태로 같은 모양의 블록이 모이면 다시 지워지고 떨어지고를 반복하게 된다. 문제 풀이블록2X2가 같을 경우 지워지고 2X2블록과 겹..
2021.10.12
728x90

문제


ROR 게임은 두 팀으로 나누어서 진행하며, 상대 팀 진영을 먼저 파괴하면 이기는 게임입니다. 따라서, 각 팀은 상대 팀 진영에 최대한 빨리 도착하는 것이 유리합니다. 

지금부터 당신은 한 팀의 팀원이 되어 게임을 진행하려고 합니다. 다음은 5 x 5 크기의 맵에, 당신의 캐릭터가 (행: 1, 열: 1) 위치에 있고, 상대 팀 진영은 (행: 5, 열: 5) 위치에 있는 경우의 예시입니다.

위 그림에서 검은색 부분은 벽으로 막혀있어 갈 수 없는 길이며, 흰색 부분은 갈 수 있는 길입니다. 캐릭터가 움직일 때는 동, 서, 남, 북 방향으로 한 칸씩 이동하며, 게임 맵을 벗어난 길은 갈 수 없습니다.
아래 예시는 캐릭터가 상대 팀 진영으로 가는 두 가지 방법을 나타내고 있습니다.

  • 첫 번째 방법은 11개의 칸을 지나서 상대 팀 진영에 도착했습니다.

  • 두 번째 방법은 15개의 칸을 지나서 상대팀 진영에 도착했습니다.

위 예시에서는 첫 번째 방법보다 더 빠르게 상대팀 진영에 도착하는 방법은 없으므로, 이 방법이 상대 팀 진영으로 가는 가장 빠른 방법입니다.

만약, 상대 팀이 자신의 팀 진영 주위에 벽을 세워두었다면 상대 팀 진영에 도착하지 못할 수도 있습니다. 예를 들어, 다음과 같은 경우에 당신의 캐릭터는 상대 팀 진영에 도착할 수 없습니다.

게임 맵의 상태 maps가 매개변수로 주어질 때, 캐릭터가 상대 팀 진영에 도착하기 위해서 지나가야 하는 칸의 개수의 최솟값을 return 하도록 solution 함수를 완성해주세요. 단, 상대 팀 진영에 도착할 수 없을 때는 -1을 return 해주세요.

제한사항

  • maps는 n x m 크기의 게임 맵의 상태가 들어있는 2차원 배열로, n과 m은 각각 1 이상 100 이하의 자연수입니다.
    • n과 m은 서로 같을 수도, 다를 수도 있지만, n과 m이 모두 1인 경우는 입력으로 주어지지 않습니다.
  • maps는 0과 1로만 이루어져 있으며, 0은 벽이 있는 자리, 1은 벽이 없는 자리를 나타냅니다.
  • 처음에 캐릭터는 게임 맵의 좌측 상단인 (1, 1) 위치에 있으며, 상대방 진영은 게임 맵의 우측 하단인 (n, m) 위치에 있습니다.

입출력 예

maps                                                                                                                                                                                   answer

[[1,0,1,1,1],[1,0,1,0,1],[1,0,1,1,1],[1,1,1,0,1],[0,0,0,0,1]] 11
[[1,0,1,1,1],[1,0,1,0,1],[1,0,1,1,1],[1,1,1,0,0],[0,0,0,0,1]] -1

 

풀이


최단거리를 구하는 문제이기 때문에 BFS를 이용하여 풀었다.

상하좌우를 모두 확인할 수 있게 하고, maps[][] == 0이면 못가고 이미 방문해서 확인했던 곳이면 visited[][]를 true로 바꾸어 방문여부를 검증해준다.

마지막칸에 도달하지 못하는 경우가 있을 수도 있기때문에 map[n-1][m-1]==1이면 -1을 리턴한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import java.util.LinkedList;
import java.util.Queue;
 
 public class GameMapShortDistance {
     public int solution(int[][] maps) {
         int answer,x,y,nx,ny;
         
         //상하좌우를 모두 확인
         int [] dx = {-1,0,1,0};
         int [] dy = {0,-1,0,1};
         int n = maps.lengthint m = maps[0].length;
 
        //방문여부 검증
         boolean[][]visited = new boolean[n][m];
         Queue<Integer> que = new LinkedList<>();
         que.offer(0);que.offer(0);
         visited[0][0= true;
         while(!que.isEmpty()){
             x = que.poll();
             y = que.poll();
 
             for (int i = 0; i < dx.length; i++){
                 nx = x + dx[i];
                 ny = y + dy[i];
                 if (nx < 0 || nx >= n || ny < 0 || ny >= m)continue;
                 if (maps[nx][ny] == 0continue;
                 if (!visited[nx][ny]){
                     que.offer(nx);
                     que.offer(ny);
                     maps[nx][ny] = maps[x][y]+1;
                     visited[nx][ny] = true;
                 }
             }
         }
 
         if (maps[n-1][m-1== 1){
            
            answer = -1;
        }
 
         answer = maps[n-1][m-1];
 
         return answer;
     }
 }
cs

 

728x90
728x90

https://programmers.co.kr/learn/courses/30/lessons/81303

 

코딩테스트 연습 - 표 편집

8 2 ["D 2","C","U 3","C","D 4","C","U 2","Z","Z"] "OOOOXOOO" 8 2 ["D 2","C","U 3","C","D 4","C","U 2","Z","Z","U 1","C"] "OOXOXOOO"

programmers.co.kr

 

문제


  • "U X": 현재 선택된 행에서 X칸 위에 있는 행을 선택합니다. 
  • "D X": 현재 선택된 행에서 X칸 아래에 있는 행을 선택합니다. 
  • "C" : 현재 선택된 행을 삭제한 후, 바로 아래 행을 선택합니다. 단, 삭제된 행이 가장 마지막 행인 경우 바로 윗 행을 선택합니다.
  • "Z" : 가장 최근에 삭제된 행을 원래대로 복구합니다. 단, 현재 선택된 행은 바뀌지 않습니다.

처음 표의 행 개수를 나타내는 정수 n, 처음에 선택된 행의 위치를 나타내는 정수 k, 수행한 명령어들이 담긴 문자열 배열 cmd가 매개변수로 주어질 때, 모든 명령어를 수행한 후 표의 상태와 처음 주어진 표의 상태를 비교하여 삭제되지 않은 행은 O, 삭제된 행은 X로 표시하여 문자열 형태로 return 하도록 solution 함수를 완성해주세요.

 

제한사항

  • 5 ≤ n ≤ 1,000,000
  • 0 ≤ k < n
  • 1 ≤ cmd의 원소 개수 ≤ 200,000
    • cmd의 각 원소는 "U X", "D X", "C", "Z" 중 하나입니다.
    • X는 1 이상 300,000 이하인 자연수이며 0으로 시작하지 않습니다.
    • X가 나타내는 자연수에 ',' 는 주어지지 않습니다. 예를 들어 123,456의 경우 123456으로 주어집니다.
    • cmd에 등장하는 모든 X들의 값을 합친 결과가 1,000,000 이하인 경우만 입력으로 주어집니다.
    • 표의 모든 행을 제거하여, 행이 하나도 남지 않는 경우는 입력으로 주어지지 않습니다.
    • 본문에서 각 행이 제거되고 복구되는 과정을 보다 자연스럽게 보이기 위해 "이름" 열을 사용하였으나, "이름"열의 내용이 실제 문제를 푸는 과정에 필요하지는 않습니다. "이름"열에는 서로 다른 이름들이 중복없이 채워져 있다고 가정하고 문제를 해결해 주세요.
  • 표의 범위를 벗어나는 이동은 입력으로 주어지지 않습니다.
  • 원래대로 복구할 행이 없을 때(즉, 삭제된 행이 없을 때) "Z"가 명령어로 주어지는 경우는 없습니다.
  • 정답은 표의 0행부터 n - 1행까지에 해당되는 O, X를 순서대로 이어붙인 문자열 형태로 return 해주세요.

정확성 테스트 케이스 제한 사항

  • 5 ≤ n ≤ 1,000
  • 1 ≤ cmd의 원소 개수 ≤ 1,000

 

풀이


처음 풀 때는 링크드리스트와 스택을 이용할려고 했으나 계속 시간초과가 나서 고민하다가 다른분의 풀이를 참고 하면서 풀다보니 굳이 링크드리스트를 사용하지 않고 Z의 기능만 스택으로 구현해주고 푸는 방법으로 풀어보게되었다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import java.util.Stack;
 
 public class EditTable {
     public String solution(int n, int k, String[] cmd) {
         
         //삭제 된 값을 순서대로 저장할 스택
         Stack<Integer> remove_val = new Stack<>();
         int table_size = n;
 
         for(int i = 0; i < cmd.length; i++){
             char c = cmd[i].charAt(0);
 
             //D면 정수형으로 변환해서 +
             if (c == 'D'){
                 k+= Integer.parseInt(cmd[i].substring(2));
             }
 
             //U면 정수형으로 변환해서 -
             else if (c == 'U'){
                 k-=Integer.parseInt(cmd[i].substring(2));
             }
 
             //C면 정수형으로 변환해서 삭제스택에다가 현재 포커스값을 넣는다.그다음 테이블 사이즈 줄여줌
             else if (c == 'C'){
                 remove_val.add(k);
                 table_size --;
 
                 //만약 k값이 마지막위치에 있다면 k값을 빼준다.
                 if (k == table_size){
                     k--;
                 }
 
                 //Z이면 스택에서 값을 빼낸다 만약 K값이 스택에서 나온값과 같다면 k++
             }else if (c == 'Z'){
                 if (remove_val.pop()<=k){
                     k++;
                 }
 
                 //표 사이즈 늘려줌
                 table_size++;
             }
         }
         StringBuilder sb = new StringBuilder();
 
         //현재 표 크기만큼 0을 채워넣는다.
         for(int i = 0; i<table_size; i++){
                 sb.append("O");
         }
 
         //스택에 k값을 넣었기때문에 insert로 k를 빼내서 k번째 자리에 X를 채워준다.
         while (!remove_val.isEmpty()){
             sb.insert(remove_val.pop(),"X");
         }
 
         String answer = sb.toString();
 
         return answer;
     }
 }
cs

 

728x90
728x90

🪙운영서버 


운영 서버는 개발이나 테스트 목적이 아닌 실제 사용자들을 대상으로 서비스하는 서버를 의미한다. 테스트 목적의 서버라면 많은 요청이 발생할 일도 없고 장애가 발생하더라도 금전적인 문제나 큰 문제가 발생하지 않는다. 하지만 운영 서버는 테스트 목적의 서버와는 다르게 트래픽 대응도 해야 하고 빠은 응답 속도와 높은 가용성을 보장해야 한다. 그러기 위해서는 운영 서버는 테스트 서버와 다르게 다양한 구성 요소를  포함해야 한다.

 

운영 서버 관리에는 세 단계가 있다. 운영 서버 관리는 크게 '환경 구성' , '코드 배포' , '모니터링'으로 나뉜다.

  • 환경 구성은 서비스할 코드를 구동시킬 수 있는 서버 인프라를 구축하는 것이다.
  • 코드 배포는 환경 구성 과정에서 구성한 최신 버전의 코드를 빠르고 안전하게 배포하는 것이다.
  • 모니터링은 안정적인 서비스 운영을 위해 서버와 코드에 어떤 이상이 없는지 바로 파악하고 대응할 수 있게 도와준다.
  • 위처럼 운영 서버 환경 구성을 AWS(Amazon Web Services)라는 클라우드 서비스로 할 수 있다.

 

🪙클라우드 서비스(AWS) 플랫폼을 써야 하는 이유


꼭 AWS를 쓰지 않더라도 클라우드 서비스 플랫폼은 기존의 운영 서버 관리 방식보다 훨씬 많은 이점을 가져다준다.

블로그에서 다른 클라우드 서비스도 있지만 지금 공부하는 클라우드 서비스가  AWS(Amazon Web Services)이기 때문에 예를  AWS(Amazon Web Services)로 들것이다.

예전에는 서버를 직접 구매한 후 회사나 IDC에 설치해서 관리해야 했다. 이 서버들이 문제없이 돌아가게 하기 위한 전문 인력들이 필요했다. 서버뿐만 아니라 서버에 설치되는 수많은 인프라에 대해서도 전문 인력들이 필요했다. 그리고 유연하게 서버를 늘리거나 줄이기 힘들기 때문에 서버를 넉넉하게 구매해놓고 사용하지 않는 비효율적인 자원 낭비가 심했다.

하지만 클라우드 서비스를 이용할 경우 필요한 사양의 서버를 몇 번의 클릭만으로 추가하거나 제거할 수 있고 사용한 시간만큼만 금액을 지불하게 된다. 또한 클라우드 서비스 제공 업체에는 전문적인 인력들이 있어서 개개인이 안정성이나 성능에 대해서도 고민을 줄일 수 있다.

즉 훨씬 적은 비용 , 시간, 인력으로도 큰 규모의 서비스를 운영할 수 있는 것이다.

 

 

🪙운영 서버 구성 


1. 단일 서버

가장 기본적인 구성이다. 요청을 보내는 클라이언트와 요청을 처리하는 서버가 한 대 있다. 여기서 얘기하는 클라이언트는 우리가 흔히 사용하는 휴대폰 앱이나 크롬 같은 웹 브라우저 등을 의미한다. 서버 내에는 애플리케이션 코드와 데이터 베이스가 실행된다. 매우 단순한 구성인 만큼 환경을 구축하기 쉽기 때문에 테스트 서버나 간단한 애플리케이션을 서비스할 때 많이 사용된다. 그리고 데이터베이스와 애플리케이션이 같은 서버에서 실행되고 있기 때문에 별도의 네트워크 설정을 할 필요 없이 로컬 호스트를 상대로 테스트를  할 수 있다. 그러나 생각보다 많은 단점이 존재한다.

  • 전체 서비스에 장애가 생길 확률이 높다.
    • 애플리케이션과 데이터베이스가 같은 자원을 공유하기 때문에 둘 중 하나라도 자원을 모두 사용 해버 리거나 서버 하드웨어에 장애가 발생하면 서비스 전체가 죽어버린다.
  • 서버 자원을 효율적으로 사용하기 어렵다.
    • 애플리케이션과 데이터베이스는 각 속성에 따라 더 중요한 자원의 종류나 최적화를 위한 OS설정(I/O 컨트롤러, 디스크 설정)이 다를 수 있다.
    • 둘 다 만족시키기 위해서는 필요 이상으로 고사양 서버를 사용해야 할 수도 있다.
  • 보안성이 떨어진다.
    • 데이터베이스는 보안상 포트나 IP 등 접속 지점을 최소한으로 하는 것이 좋다. 하지만 웹 애플리케이션 특성상 다양한 IP주소와 포트 번호에 대해 요청을 받을 수 있어야 하고 서버 내 여러 파일들도 업로드될 수 있으므로 데이터 베이스가 공격당할 가능성이 높아진다.
  • 서버의 수를 여려대로 늘려서 자원을 확장하는 스케일 아웃(Scale out)이 힘들다.
    • 서버를 여러 대로 늘려야 하는 경우 클라이언트에서는 추가된 서버들의 주소를 새로 알아야 하며 데이터도 똑같은 복제본이 생기므로 비효율적이고 관리하기 힘들어진다.

 

2. 애플리케이션 /데이터베이스 서버 분리

단일 서버 구성에서 데이터베이스를 별도의 서버로 분리한 구성이다. 애플리케이션과 데이터베이스가 다른 자원을 사용하기 때문에 단일 서버에서 나온 전체 서비스 장애 확률, 효율적인 자원 사용, 떨어지는 보안성과 같은 단점들이 해결된다. 

다만 서버 두 개를 관리하기 때문에 구성이 조금 더 복잡해지고 서버 사이의 지연 시간과 네트워크 보안을 고려하기 시작해야 한다. 그리고 클라이언트에서는 하나의 서버를 바라보고 있기 때문에 서버 자원 확장을 위해 서버의 수를 늘리는 스케일 아웃(Scale out)은 여전히 힘들다.

 

 

3. 서버 단위의 로드 밸런서

 

클라이언트가 애플리케이션을 실행하는 서버와 직접 통신하는 대신 로드 밸런서라는 서버와 통신하고 그 뒤에 여러 대의 애플리캐이션 서버를 두는 방식이다. 클라이언트는 로드 밸런서 하고만 통신하고 로드 밸런서가 클라이언트에게 받은 요청을 뒤에 있는 서버들에게 나눠준다. 뒤에 있는 서버들이 요청을 처리하면 로드 밸런서를 통해 클라이언트에게 전달된다.

이 구성의 가장 큰 장점은 스케일 아웃이 가능해진다는 것이다. 애플리케이션 서버 중 일부 서버에 장애가 발생해도 로드 밸런서에서 정상 서버에만 요청을 주면 되기 때문에 서비스 장애를 최소화할 수 있다. 다만 모든 요청이 로드 밸런서를 통해 지나가기 때문에 로드 밸런서에 장애가 생기면 나머지 서버들이 정상이어도 전체 서비스 장애로 이어지기 때문에 주의해야 한다. 그리고 구성이 매우 복잡해진다는 단점이 있다.

+OSI 7 Layer의 L4 스위치라고 얘기하는 것이 이 로드 밸런서의 역할을 하는 장비다.

4. 서버 내 앱 단위의 로드 밸런서 

 

여러 서버에게 요청을 분산하는 서버 단위의 로드 밸런서 외에도 여러 애플리케이션 프로세스들에 요청을 분산시키는 애플리케이션 단위의 로드 밸런서가 추가됐다. 애플리케이션 서버 안에서 똑같은 애플리케이션을 여러 프로세스로 만들어 실행해 놓고 외부에서 들어온 요청을 프로세스 중 하나로 보내주는 역할을 하는 방식이다. 이처럼 구성할 경우 하나의 서버에 여러 개의 프로세스를 실행에 하나의 서버에서 여러 개의 요청을 동시에 처리할 수 있으며 서버 자원을 최대한으로 사용할 수 있는 만큼의 프로세스를 실행해 서버 자원도 더욱 효율적으로 사용할 수 있다.

 

 


REFERENCE

  • 서비스 운영이 쉬워지는 AWS 인프라 구축 가이드 
728x90
728x90

문제 설명

0과 1로 이루어진 2n x 2n 크기의 2차원 정수 배열 arr이 있습니다. 당신은 이 arr을 쿼드 트리와 같은 방식으로 압축하고자 합니다. 구체적인 방식은 다음과 같습니다.

  1. 당신이 압축하고자 하는 특정 영역을 S라고 정의합니다.
  2. 만약 S 내부에 있는 모든 수가 같은 값이라면, S를 해당 수 하나로 압축시킵니다.
  3. 그렇지 않다면, S를 정확히 4개의 균일한 정사각형 영역(입출력 예를 참고해주시기 바랍니다.)으로 쪼갠 뒤, 각 정사각형 영역에 대해 같은 방식의 압축을 시도합니다.

arr이 매개변수로 주어집니다. 위와 같은 방식으로 arr을 압축했을 때, 배열에 최종적으로 남는 0의 개수와 1의 개수를 배열에 담아서 return 하도록 solution 함수를 완성해주세요.


제한사항

  • arr의 행의 개수는 1 이상 1024 이하이며, 2의 거듭 제곱수 형태를 하고 있습니다. 즉, arr의 행의 개수는 1, 2, 4, 8, ..., 1024 중 하나입니다.
    • arr의 각 행의 길이는 arr의 행의 개수와 같습니다. 즉, arr은 정사각형 배열입니다.
    • arr의 각 행에 있는 모든 값은 0 또는 1 입니다.

입출력 예

arrresult

[[1,1,0,0],[1,0,0,0],[1,0,0,1],[1,1,1,1]] [4,9]
[[1,1,1,1,1,1,1,1],[0,1,1,1,1,1,1,1],[0,0,0,0,1,1,1,1],[0,1,0,0,1,1,1,1],[0,0,0,0,0,0,1,1],[0,0,0,0,0,0,0,1],[0,0,0,0,1,0,0,1],[0,0,0,0,1,1,1,1]] [10,15]

입출력 예 설명

입출력 예 #1

  • 다음 그림은 주어진 arr을 압축하는 과정을 나타낸 것입니다.
  • 최종 압축 결과에 0이 4개, 1이 9개 있으므로, [4,9]를 return 해야 합니다.

입출력 예 #2

  • 다음 그림은 주어진 arr을 압축하는 과정을 나타낸 것입니다.
  • 최종 압축 결과에 0이 10개, 1이 15개 있으므로, [10,15]를 return 해야 합니다.

풀이 

주어진 맵을 정확하게 4개의 정사각형으로 압축해 나갔을 때, 최종적으로 남는 0과 1의 개수를 구하는 문제이다.

가장 완쪽 위의 좌표를 기준으로 , 현재 탐색하고자 하는 정사각형의 한변의 길이를 통해서 탐색하는 것이다.

특정 범위를 탐색했을 때, 주어질 수 있는 경우의 수는 3가지이다.

1.  특정 범위가 모두 0인 경우

2. 특정 범위가 모두 1인 경우 

3. 1,2번이 모두 아닌 경우

만약 1번이나 2번에 부합하는 경우 정사각형을 나누는 과정이 필요하지 않다. 왜냐하면 더 이상 압축이 되질 않기 때문이다.

3번의 경우에만 정사각형을 잘라야한다.정사각형을 자르는 경우는 재귀를 통해서 구현한다.

나눌 경우에는 가장 왼쪽위의 좌표를 기준으로 나눌수 있다.

처음에[(0,0),4]라는 사각형 위에서 판별하고 나눈다. 정사각형으로 나눠 보면 

1번 사각형 : [ (0 , 0) , 2 ]

2번 사각형 : [ (0 , 2) , 2 ]

3번 사각형 : [ (2 , 0) , 2 ]

4번 사각형 : [ (2 , 2) , 2 ]

으로 나눌수 있다. 나눠질 4개의 사각형의 좌표와 한변의 길이는 다음과 같다.

1번 사각형 : [ (x , y) , length / 2 ]

2번 사각형 : [ (x , y + length / 2) , length / 2 ]

3번 사각형 : [ (x + length / 2 , y) , length/ 2 ]

4번 사각형 : [ (x + length / 2 , y + length / 2) , length / 2 ]

이 4개의 영역을 재귀로 풀이하면 답을 구할 수 있다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class QuadCompressionCount {
    int[] answer = new int[2];
    public int[] solution(int[][] arr) {
        quad(arr.length0,0 ,arr);
        return answer;
    }
 
    private void quad(int lengthint x, int y, int[][] arr) {
 
        boolean Zero = true;
        boolean One = true;
 
        for(int i = x; i <  x+length; i++){
            for(int j = y; j < y+length; j++){
                if (arr[i][j] == 1)Zero = false;
                if (arr[i][j] == 0)One = false;
            }
        }
 
        if (Zero){
            answer[0++;
            return;
        }else if (One){
            answer[1]++;
            return;
        }
 
        quad(length/2,x,y,arr);
        quad(length/2,x+length/2,y,arr);
        quad(length/2,x,y+length/2,arr);
        quad(length/2,x + length/2,y + length/2,arr);
    }
 
 
}
 
cs
728x90
728x90

문제 설명

N개의 마을로 이루어진 나라가 있습니다. 이 나라의 각 마을에는 1부터 N까지의 번호가 각각 하나씩 부여되어 있습니다. 각 마을은 양방향으로 통행할 수 있는 도로로 연결되어 있는데, 서로 다른 마을 간에 이동할 때는 이 도로를 지나야 합니다. 도로를 지날 때 걸리는 시간은 도로별로 다릅니다. 현재 1번 마을에 있는 음식점에서 각 마을로 음식 배달을 하려고 합니다. 각 마을로부터 음식 주문을 받으려고 하는데, N개의 마을 중에서 K 시간 이하로 배달이 가능한 마을에서만 주문을 받으려고 합니다. 다음은 N = 5, K = 3인 경우의 예시입니다.

위 그림에서 1번 마을에 있는 음식점은 [1, 2, 4, 5] 번 마을까지는 3 이하의 시간에 배달할 수 있습니다. 그러나 3번 마을까지는 3시간 이내로 배달할 수 있는 경로가 없으므로 3번 마을에서는 주문을 받지 않습니다. 따라서 1번 마을에 있는 음식점이 배달 주문을 받을 수 있는 마을은 4개가 됩니다.
마을의 개수 N, 각 마을을 연결하는 도로의 정보 road, 음식 배달이 가능한 시간 K가 매개변수로 주어질 때, 음식 주문을 받을 수 있는 마을의 개수를 return 하도록 solution 함수를 완성해주세요.

제한사항

  • 마을의 개수 N은 1 이상 50 이하의 자연수입니다.
  • road의 길이(도로 정보의 개수)는 1 이상 2,000 이하입니다.
  • road의 각 원소는 마을을 연결하고 있는 각 도로의 정보를 나타냅니다.
  • road는 길이가 3인 배열이며, 순서대로 (a, b, c)를 나타냅니다.
    • a, b(1 ≤ a, b ≤ N, a != b)는 도로가 연결하는 두 마을의 번호이며, c(1 ≤ c ≤ 10,000, c는 자연수)는 도로를 지나는데 걸리는 시간입니다.
    • 두 마을 a, b를 연결하는 도로는 여러 개가 있을 수 있습니다.
    • 한 도로의 정보가 여러 번 중복해서 주어지지 않습니다.
  • K는 음식 배달이 가능한 시간을 나타내며, 1 이상 500,000 이하입니다.
  • 임의의 두 마을간에 항상 이동 가능한 경로가 존재합니다.
  • 1번 마을에 있는 음식점이 K 이하의 시간에 배달이 가능한 마을의 개수를 return 하면 됩니다.

입출력 예

N           road                                                                                                                                                                K.       result

5 [[1,2,1],[2,3,3],[5,2,2],[1,4,2],[5,3,1],[5,4,2]] 3 4
6 [[1,2,1],[1,3,2],[2,3,2],[3,4,3],[3,5,2],[3,5,3],[5,6,1]] 4 4

입출력 예 설명

입출력 예 #1
문제의 예시와 같습니다.

입출력 예 #2
주어진 마을과 도로의 모양은 아래 그림과 같습니다.


1번 마을에서 배달에 4시간 이하가 걸리는 마을은 [1, 2, 3, 5] 4개이므로 4를 return 합니다.


풀이

플로이드 와샬 알고리즘을 사용해서 풀이하였다. 플로이드 와샬 알고이즘을 간단하게 설명하면 그래프에서 모든 정점 사이의 최단거리를 구하는 알고리즘이다.

N크기 만큼 2차원 배열을 만들어서 road배열의 요소를 가져온다.

여기서 도로는 중복되어 있을수 있으므로 가져오는 배열이 기존에 존재하는 배열보다 큰 경우 무시한다.(최단거리를 구하는 것이기 때문에 중복되는 도로중에 큰것은 덮어쓰기 때문에 무시한다.)

1번째 도시에서 부터 거리K를 확인하는 것이기 때문에 0정점(1번째 도시)에 연결되어 있는 거리가 K를 넘는지 확인하면 문제가 마무리된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public class delivery {
    public int solution(int N, int[][] road, int K) {
        int answer = 0;
        int [][] val = new int[N][N];
        for(int i = 0; i < val.length;i++){
            for(int j = 0; j < val[0].length; j++){
                if (i == j){
                    val[i][j] = 0;
                    continue;
                }
                val[i][j] = 500001;
            }
        }
        for(int i = 0; i < road.length; i++){
            if (val[road[i][0]-1][road[i][1]-1< road[i][2])continue;
            val[road[i][0]-1][road[i][1]-1= road[i][2];
            val[road[i][1]-1][road[i][0-1= road[i][2]; //양방향이 가능하므로 양쪽으로 값을 삽입
        }
 
        for(int i = 0; i < N; i++){
            for(int j = 0; j < N; j++){
                for(int k = 0; k < N; k++){
                    if (j == k) continue;
                    if (val[j][k] > val[j][i]+val[i][k]){
                        val[j][k] = val[j][i]+val[i][k];
                    }
                }
            }
        }
 
        //0정점(1번째 도시)에 연결되어 있는 거리가 K를 넘는지 확인
        for (int i = 0; i < val[0].length; i++){
            if (val[0][i] <= K){
                answer++;
            }
        }
        return answer;
    }
}
 
cs
728x90
728x90

JPA는 개발하는 입장에서 매우 편리하고 설정만 잘하면 편할거라고 생각하는데  사용하기 편하고 쉬운만큼 성능적인 측면에서 생각하지 못한 이슈가 발생할 수 있다.이번에 정리할 이슈는 즉시로딩(EAGER Loading)과 지연로딩(LAZY Loading)이다.

@OneToOne 매핑시에 지연로딩(LAZY Loading)로 설정해도 즉시로딩(EAGER Loading)로 작동하는 경우가 있다.이번 포스팅에서는 발생하는 이슈에 대해서 해결책을 적어보려한다.


일단 정상적으로 작동하는 예제이다. 일대일 단방향 매핑으로 외래키를 가지고 있는 USER가 연관관계 주인이다. 여기서 유저를 조회하면 어떻게 쿼리가 작동하는지 보자 

 

이처럼 이름으로 조회하면 

 

 

  select
        user0_.user_id as user_id1_1_,
        user0_.name as name2_1_,
        user0_.studygroup_id as studygro3_1_ 
    from
        user user0_ 
    where
        user0_.name=?
 
 

지연 로딩이 정상적으로 작동한다. 그러면 도대체 어디에서 이슈가 발생할까?

이제 이슈에 대해서 다뤄보겠다.

 

위 예시는 USER와 STUDYGROUP이 일대일 양방향 관계를 가지고 있다.여기에서 또한 연관관계의 주인은 외래키를 가지고있는 USER이다.

여기서 USER를 조회하면 정상적으로 지연로딩이 작동한다.

그러나 STUDYGROUP을 조회하면 아래처럼 지연로딩이 작동하지 않고 즉시로딩이 작동한다.

 

 

select
        studygroup0_.id as id1_4_0_ 
    from
        studygroup studygroup0_ 
    where
        studygroup0_.id=?

  select
        user0_.user_id as user_id1_1_,
        user0_.name as name2_1_,
        user0_.studygroup_id as studygro3_1_ 
    from
        user user0_ 
    where
        user0_.studygroup_id=?

 

 

fetch전략을 지연로딩으로 설정했음에도 불구하고 즉시로딩으로 유저를 조회하는 비효율적이고 불필요한 쿼리가 발생한다.

 

이러한 이슈의 원인은 지연로딩은 로딩되는 시점에 엔티티를 프록시객체로 가져온다.여기서는 문제가 발생하지 않지만 이후에는 StudyGroup 객체를 가져오는 시점에는 실제 객체가 사용된다.

지연로딩으로 설정이 되어있는 엔티티를 조회할 때에는 프록시로 감싸서 동작한다.그러나 프록시의 한계로 null을 감싸지못한다. 그래서 이러한 문제가 발생한다.

 

StudyGroup라는 테이블에는 USER를 참조할 수 있는 컬럼이 존재하지 않는다. 따라서 StudyGroup는 어떤 USER에 의해 참조되고 있는지 알 수 없다.

StudyGroup가 어떤 USER에 의해 참조되고 있는지 알 수 없다는 뜻은 만약 USER가 null이더라도 StudyGroup는 이 사실을 알지 못한다는 것이다.

만약 USER가 null이 아니라고 해도, StudyGroup의 입장에서는 USER가null인지 null이 아닌지 확인할 방법이 없다.

따라서 USER의 존재 여부를 확인하는 쿼리를 실행하기 때문에 지연 로딩으로 동작하지 않는 것이다.

 


해결책 

  • 양방향 매핑이 반드시 필요한지 검토해본다.
  • 다대일이나 일대다로 관계를 변경할 수 있는지 고민해본다.
  • StudyGroup을 조회할 때 User도 같이 조회한다.(fetch join)

해결 방법이 명확하게 존재하는 것은 아니다.그래서 상황에 맞게 적용해서 사용하는것이 가장 좋다고 생각한다.

 

728x90
728x90

문제가 까다로워 보여도 점화식만 찾으면 쉽게 풀수있다.

 

풀이 

  • 5번째 자리 수는 AEIOU 순서대로 바뀔때 1씩 증가한다. =1
  • 4번째 자리 수는 AEIOU 순서대로 바뀔때 5씩 증가하지만 5번째자리에 숫자가 없는 경우를 더해 +1해서 6씩 증가한다. = 6
  • 3번째 자리 수는 AEIOU 순서대로 바뀔때 4번째 자리 수 증가율 *3번째 자리 수 증가율+3번째 자리까지만 있는 경우(6 *5 +1 )증가한다. =31
  • 2번째 자리 수는 AEIOU 순서대로 바뀔때 3번째 자리 수 증가율 (31)* 2번째 자리 수 증가율(5) +2번째 자리까지만 있는 경우(+1) 씩 증가한다 식은 (31*5+1) .= 156
  • 1번째 자리 수는 AEIOU 순서대로 바뀔때 2번째 자리 수 증가율 (156)* 1번째 자리 수 증가율(5) +2번째 자리까지만 있는 경우(+1) 씩 증가한다 식은 (156*5+1) = 781.
  • 이처럼 식을 구한 다음 각 자리에 맞는 수를 더해주면 된다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class VowelDictionary {
    public int solution(String word) {
        String words = "AEIOU";
        int[] var = {781,156,31,6,1};
        int index = word.length();
        int value = word.length();
        for(int i = 0; i< word.length(); i++){
            index = words.indexOf(word.charAt(i));
            value += var[i]*index;
        }
        return value;
    }
}
 
cs

처음에 보고 생각보다 감이 안잡혔던 문제다.생각만 잘하면 쉽게 구할수 있는 문제였다. 생각 잘하자!!

728x90
728x90

문제

블라인드 공채를 통과한 신입 사원 라이언은 신규 게임 개발 업무를 맡게 되었다. 이번에 출시할 게임 제목은 "프렌즈4블록".
같은 모양의 카카오프렌즈 블록이 2×2 형태로 4개가 붙어있을 경우 사라지면서 점수를 얻는 게임이다.만약 판이 위와 같이 주어질 경우, 라이언이 2×2로 배치된 7개 블록과 콘이 2×2로 배치된 4개 블록이 지워진다. 같은 블록은 여러 2×2에 포함될 수 있으며, 지워지는 조건에 만족하는 2×2 모양이 여러 개 있다면 한꺼번에 지워진다.블록이 지워진 후에 위에 있는 블록이 아래로 떨어져 빈 공간을 채우게 된다.만약 빈 공간을 채운 후에 다시 2×2 형태로 같은 모양의 블록이 모이면 다시 지워지고 떨어지고를 반복하게 된다.

 

문제 풀이

블록2X2가 같을 경우 지워지고 2X2블록과 겹쳐있는 경우에도 지워진다.

제일 처음으로 사라져야 하는 블록을 체크한 다음 체크 된 블록을 지우고 블록을 떨어트린다. 

위 과정을 더 이상 사라질 블록이 없을 때 까지 반복한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
public class Friend4Block2 {
    public int solution(int m, int n, String[] board) {
        int answer = 0;
        char[][] var = new char[m][n];
 
        for(int i = 0; i < m; ++i){
            var[i] = board[i].toCharArray();
        }
 
        while(true){
            int cnt = checkBlock(m,n,var);
            if(cnt == 0)break;
            answer += cnt;
 
            dropBlock(m,n,var);
        }
        return answer;
    }
 
    //블록 떨어트리기
    private void dropBlock(int m, int n, char[][] map) {
        for(int i = 0 ; i < n ; i++) {
            for(int j = m - 1 ; j >= 0 ; j--) {
                if(map[j][i] == '.') {
                    for(int k = j - 1 ; k >= 0 ; k--) {
                        if(map[k][i] != '.') {
                            map[j][i] = map[k][i];
                            map[k][i] = '.';
                            break;
                        }
                    }
                }
            }
        }
    }
 
    //체크된 블록 지우기
    private int checkBlock(int m, int n, char[][] var) {
        int cnt = 0;
        boolean[][]isChecked = new boolean[m][n];
 
        for(int i = 0; i < m-1; i++){
            for(int j = 0; j < n-1; j++){
                if(var[i][j] == '.')continue;
                checkFour(var,isChecked,i,j);
            }
        }
        for(int i = 0; i <  m; i++){
            for(int j = 0; j < n; j++){
                if (isChecked[i][j]){
                  //사라질 블록 갯수 세기 
                    cnt++;
//사라질 블록 '.'으로 바꾸기
                    var[i][j] ='.';
                }
            }
        }
        return cnt;
    }
    
    //사라져야할 블록
    private void checkFour(char[][] var, boolean[][] isChecked,int i,int j){
        char block = var[i][j];
 
        for (int k = i; k < i+2; k++){
            for (int l = j; l < j+2; l++){
                if (var[k][l] != block)return;
            }
        }
 
        for (int k = i; k < i+2; k++){
            for (int l = j; l < j+2; l++){
                isChecked[k][l] = true;
            }
        }
    }
}
 
cs
 
 
 

 

728x90

'Dev > 알고리즘 ,자료구조' 카테고리의 다른 글

[프로그래머스] 배달  (0) 2021.10.18
[프로그래머스]모음 사전(JAVA)  (0) 2021.10.12
[Algorithm]BeakJoon_2981  (0) 2021.07.20
[Algorithm]BeakJoon_1541  (0) 2021.07.18
[Algorithm]BeakJoon_11399  (0) 2021.07.18