문제 설명

풀이

일단 상어마다 모두 주변을 확인해서, 안전거리를 모두 구해야한다. 그렇게 생각하면 어떻게 모두 확인해볼지 생각해봐야 한다.

 

계속해서 안전거리를 추가해줘야하니 DFS나 BFS를 해줘야하는데, 끝까지 갈필요 없이, 최대한 인접한 곳을 보는 것이니 BFS로 하였다.

 

그리고 매우 기초적인 BFS라서 BFS의 흐름을 풀어보기에 좋은 문제였다.

 

코드

import java.io.*;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

public class Main {
    static int N,M;
    static int count;
    static int[][] map;
    static int[][] dis;
    static int[] dx = {-1,0,1,-1,1,-1,0,1};
    static int[] dy = {-1,-1,-1,0,0,1,1,1};

    public static void main(String[] args) throws IOException {
        // 1. 값 입력받기
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());

        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
        count = 0;
        map = new int[N+1][M+1];
        dis = new int[N+1][M+1];

        Queue<int[]> que = new LinkedList<int[]>();

        for(int i =0; i< N; i++){
            st = new StringTokenizer(br.readLine());
            for(int j =0; j<M; j++){
                map[i][j] = Integer.parseInt(st.nextToken());
                if(map[i][j] == 1){
                    que.add(new int[] {i,j});
                }
            }
        }

        while (!que.isEmpty()) {
            int[] now =  que.poll();
            int x = now[0];
            int y = now[1];

            for(int z=0; z<8; z++){
                int cx = x + dx[z];
                int cy = y + dy[z];

                if(cx < 0 || cy < 0 || cx >= M || cy >= N || map[cx][cy] == 1 || dis[cx][cy] != 0){
                    continue;
                }

                dis[cx][cy] = dis[x][y] + 1;
                if (dis[cx][cy] > count){
                    count = dis[cx][cy];
                }
                que.add(new int[] {cx,cy});
            }
        }

        System.out.println(count);

    }
}

https://www.acmicpc.net/problem/17086

 

17086번: 아기 상어 2

첫째 줄에 공간의 크기 N과 M(2 ≤ N, M ≤ 50)이 주어진다. 둘째 줄부터 N개의 줄에 공간의 상태가 주어지며, 0은 빈 칸, 1은 아기 상어가 있는 칸이다. 빈 칸의 개수가 한 개 이상인 입력만 주어진다.

www.acmicpc.net

 

문제 설명

 

풀이

연결되어있는 선들의 연결요소를 구하는 문제였다.

생각해보면, 모든 선을 체크해보면서 같은 연결요소인지 체크를 해봐야하니 DFS나 BFS가 적합하다고 판단했다.

 

좀 더 생각해보면 DFS를 통해 연결요소를 모두 찾고 visit을 체크 해준 다음, 나머지 연결 안된 요소들을 또다시 DFS로 돌리면 된다는 것을 깨달을 수 있다.

 

그래서 DFS로 풀기 시작하는데, ArrayList안에 ArrayList를 넣는 형식으로 풀이하였다

ArrayList에 정점의 갯수만큼 ArrayList를 만들어주었다.

그리고 양방향으로 선을 모두 입력시켜주었다.

마지막으로 가장 바깥의 ArrayList를 돌면서 체크가 안되어있는 정점을 DFS로 돌린다. (+ 카운트도 추가해줌)

 

DFS에서는 정점과 연결된 정점들에 대한 For문을 돌리면서 다시 DFS를 돌리면 완성!!

 

중간에 visit을 체크해주면서 dfs를 돌리고 answer를 추가해주는게 핵심이다!!

 

깨닫게 된 점

  • DFS 내부에서 visit = true를 설정해주어야 한다.
  • visit를 1차원 배열로만 사용해도 되는데 너무 힘들게 생각했다.
  • 점마다 visit안한 정점을 DFS로 돌리고, 연결된 것들을 함수내에서 다시 for문으로 실행시키면 된다.

 

코드

 

import java.io.*;
import java.util.ArrayList;
import java.util.StringTokenizer;

public class Main {
    static int N,M;
    static ArrayList<ArrayList<Integer>> dots;
    static int count;
    static boolean[] visit;

    public static void main(String[] args) throws IOException {
        // 1. 값 입력받기
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());

        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
        dots = new ArrayList<>();

        for(int i=1; i< N+2; i++){
            dots.add(new ArrayList<Integer>());
        }

        for(int i =0; i< M; i++){
            st = new StringTokenizer(br.readLine());
            int a = Integer.parseInt(st.nextToken());
            int b = Integer.parseInt(st.nextToken());

            dots.get(a).add(b);
            dots.get(b).add(a);
        }
        visit = new boolean[N+1];
        count = 0;

        for(int i=1; i < N+1; i++){
            if(!visit[i]){ //아직 체크가 안됐을 경우
                dfs(i);
                count++;
            }
        }
        System.out.println(count);
    }

    private static void dfs(int x) {
        if (visit[x]) return;
        else{
            visit[x] = true;
            for(int i : dots.get(x)){
                if(!visit[i]){
                    dfs(i);
                }
            }
        }
    }
}

 

https://www.acmicpc.net/problem/11724

 

11724번: 연결 요소의 개수

첫째 줄에 정점의 개수 N과 간선의 개수 M이 주어진다. (1 ≤ N ≤ 1,000, 0 ≤ M ≤ N×(N-1)/2) 둘째 줄부터 M개의 줄에 간선의 양 끝점 u와 v가 주어진다. (1 ≤ u, v ≤ N, u ≠ v) 같은 간선은 한 번만 주

www.acmicpc.net

 

HTTP 메소드에 대해서 설명하세요.

내 답안 : XX

 

예비 답안 : 

CRUD관점에서 설명하기!!

Post

Get

Put

Delete

알아서 설명하기

 


HTTP1.1 vs HTTP2.0

내 답안 : 좀 더 보안이 강화됨? -이건 https인가?

 

예비 답안 : 

WWW에서 하이퍼텍스트 문서를 교환하기 위하여 사용되는 통신규약이다.

 

HTTP/1.1

Connection당 하나의 요청을 처리 하도록 설계 되어 있다. 그래서 동시전송이 불가능하고 요청과 응답이 순차적으로 이루어 지게된다. 그렇다 보니 HTTP문서안에 포함된 다수의 리소스 (CSS, JS, Images)를 처리하려면 요청할 리소스 개수에 비례해서 Latency(대기 시간)는 길어지게 된다.

HTTP/1.1 단점

  • HOL(Head Of Line) Blocking – 특정 응답의 지연
  • RTT(Round Trip Time) 증가
  • 무거운 Header 구조 (특히 Cookie)

HTTP/2.0 장점

  • Multiplexed Streams
    • 한 커넥션으로 동시에 여러개의 메세지를 주고 받을 있으며, 응답은 순서에 상관없이 stream으로 주고 받는다. HTTP/1.1의 Connection Keep-Alive, Pipelining의 개선이라 보면 된다.
  • Stream Prioritization
  • 예를 들면 클라이언트가 요청한 HTML문서안에 CSS파일 1개와 Image파일 2개가 존재하고 이를 클라이언트가 각각 요청하고 난 후 Image파일보다 CSS파일의 수신이 늦어지는 경우 브라우저의 렌더링이 늦어지는 문제가 발생한다. HTTP/2의 경우 리소스간 의존관계(우선순위)를 설정하여 이런 문제를 해결하고 있다.
  • Server Push
    • 서버는 클라이언트의 요청에 대해 요청하지도 않은 리소스를 마음대로 보내줄 수 도 있다.
    • 클라이언트가 HTML문서를 요청했고 해당 HTML에 여러개의 리소스(CSS, Image…) 가 포함되어 있는경우 HTTP/1.1에서 클라이언트는 요청한 HTML문서를 수신한 후 HTML문서를 해석하면서 필요한 리소스를 재 요청한다.
    • HTTP/2에선 Server Push를 이용하면 클라이언트가 요청하지도 않은 (HTML문서에 포함된 리소스) 리소스를 Push 해주는 방법으로 클라이언트의 요청을 최소화 해서 성능 향상을 이끌어 낸다.
    • 이를 PUSH_PROMISE 라고 부르며 PUSH_PROMISE를 통해서 서버가 전송한 리소스에 대해선 클라이언트는 요청을 하지 않는다.

URL 에 www.example.com 을 쳤을 때 일어나는 일들을 설명하세요.

내 답안 : X

 

예비 답안 : 

https://owlgwang.tistory.com/1

 

웹 브라우저에 URL을 입력하면 어떤 일이 일어날까?

우리가 흔히 쓰는 웹 브라우저(Chrome, Internet Explorer, Firefox)에 URL(Uniform Resource Locator)을 입력하고 Enter를 치면 어떻게 웹페이지가 우리 눈에 보여질까? 1. 주소표시줄에 URL을 입력하고 Enter를..

owlgwang.tistory.com

 

 

참고 : 

https://github.com/brave-people/brave-tech-interview/blob/main/contents/network.md

 

Key에 대해서 설명하세요. 후보키, 기본키(Primary Key), 대체키(Alternate Key), 외래키(Foreign Key), 슈퍼키(Super Key) 란?

 

나의 대답 : 

후보키 : 유일성과 최소성을 모두 가지는 속성의 집합

기본키 : 한개 선택된 키

대체키 : 기본키를 제외한 후보키

왜래키 : 다른 테이블끼리 관계를 맺을때 사용되는 키

슈퍼키 : 최소성 없이 유일성만 만족하는 키

 

모범 답안 : 

NoSQL이란?

나의 대답 : 

관계형 데이터베이스가 아닌 키-밸류 구조로 된 자율적 형태로 구성가능한 데이터 베이스 

 

모범 답안 : 

NO-SQL이란 Not Only SQL의 약자로써 기존 SQL에 비해서 특정 기능에 대해서 더 나은 기능을 제공합니다. 보통 json형태의 도큐먼트 형식으로 데이터를 저장하고 확장성이 좋기 떄문에 비정형 데이터를 다루는데 좋습니다. DB로는 대표적으로 Mongo DB가 있습니다.

트랜잭션이란?

나의 대답 : 

여러개의 SQL 명령문을 한꺼번에 실행시키는 것, ACID 만족해야함 (이건 프로시저임;;)

 

모범 답안 : 

데이터베이스의 상태를변화시키는 일의 단위


참고 : https://github.com/brave-people/brave-tech-interview/blob/main/contents/database.md

 

관계형 데이터베이스의 구성요소에 대해서 설명하세요.

 

-> Table, Attribute, row, column 등등?

 

모범답안 : 

  • 데이터가 테이블에 저장
  • 구성요소 : 행(튜플), 열(속성)
  • 행은 순서가 없지만, 열은 순서가 있다.
  • 스키마 : 이름과 데이터 유형을 정의
  • 키 : 테이블에서 특정 행을 유일하게 식별할 수 있게하는 특징, 열 혹은 복수의 열 모음
  • 테이블의 각 행에는 primary key값이 반드시 있어야 한다.
  • 외부키
  • 이용하여 다른 테이블과 링크할 수 있다.
  • 그 값이 다른 테이블의 키 열의 값과 같은 열

Key란? Key의 종류에 대해서 설명하세요.

 

-> 테이블에서 특정행을 유일하게 식별할 수 있는 속성, 열, 복수의 열 모음

종류 : 

Primary Key : 

  • 릴레이션에서 튜플을 구별하기 위해 여러 개의 후보키를 사용할 필요는 없습니다. 데이터베이스 설계자는 여러 후보키 중에서 기본적으로 사용할 키를 선택하는데 이것이 기본키입니다.

Foriegn Key

  • 어떤 릴레이션에 소속된 속성 또는 속성 집합이 다른 릴레이션의 기본키가 되는 키입니다.

Alternative Key

  • 기본키로 선택되지 못한 후보키들입니다.

Candidate Key

  • 유일성과 최소성을 만족하는 속성 또는 속성들의 집합입니다. 최소성은 키를 구성하는 여러 속성 중에 하나라도 없으면 튜플을 유일하게 구별할 수 없는 꼭 필요한 최소한의 속성들로만 키를 구성하는 특성입니다.

Super Key

  • 유일성의 특성을 만족하는 속성 또는 속성들의 집합입니다.

ACID란?

 

-> 데이터베이스 트랜잭선이 안전하게 수행되는 것을 보장하기 위한 성질

Atomicity (원자성) - 한번에 다 되거나, 다 안되거나

Consistency (일관성) - 일관성 있는 데이터베이스 유지

Isolation (고립성) - 트랜잭션 작업중에는 다른 트랜잭션에 영향 X

Durability (지속성)- 데이터 조작 완료 후 조작이 영구적이 되어 결과를 잃지 않음

 


참조 : https://github.com/brave-people/brave-tech-interview/blob/main/contents/database.md

 

1.비트연산자

 

사용하게 된 이유는 다음과 같다.

위의 사진처럼 체크한 것을 DB상에 데이터로 넣어야되는데 각각의 항목에 대해 Column을 만들기에는 너무 공간낭비가 커서 BIT를 사용해서 넣기로 하였다.

 

그래서 '권리침해~'를 예시로 들면 해당없음만 체크하면 2^0 x 1, 압류만 체크하면 2^1 x 1 이렇게 저장해주기로 했다.

그래서 front측에서는 값을 모두 바꿔서 10진수 숫자로 Backend에 넘겨주면 백엔드에서는 이걸 다시 2진수로 바꿔서 로직을 돌리고, DB에 넣을때는 결국 다시 10진수로 넣어주면 되었다.

 

그래서 지금 해야할 것은

1. JS에서 체크 된 것을 확인하고 10진수로 만들기

2. Python에서 bit연산자를 통해 2진수의 각각의 자릿수가 1인지 아닌지 체크하기

 

 

해결책.

 

1. 매우간단하다. 

str[i] * (2 ^ i) 이렇게 해주면 매우 간단하게 10진수로 변환

 

2. 

str & (1 << i) 이렇게 하면 1인지 아닌지 확인 가능하다.

 

그러면서 간단하게 비트연산자를 찾아보기도 했는데, 결국 간단한 함수들을 어떻게 활용하는지가 제일 중요한듯

 

https://dojang.io/mod/page/view.php?id=173 

 

C 언어 코딩 도장: 23.1 비트 AND, OR, XOR 연산자 사용하기

이제 비트 연산자를 사용하여 값을 계산해보겠습니다. 다음 내용을 소스 코드 편집 창에 입력한 뒤 실행해보세요. a & b a | b a ^ b bitwise_and_or_xor_operator.c #include int main() { unsigned char num1 = 1; // 0000 00

dojang.io

 

1.TypeChecker

함수에 넣을때 들어가는 파라미터가 지정해둔 정수형으로 들어가는지 체크함

아니면 바로 에러구문 표시

from inspect import getfullargspec


def type_checker(default=None):
    def get_decorator(decorated):
        spec = getfullargspec(decorated)
        argNames = spec.args
        annotations = spec.annotations

        def decorator(*args, **kwargs):
            for idx, val in enumerate(args):
                argName = argNames[idx]
                if (argName in annotations and type(val) is not annotations[argName]):
                    return default
            for key, val in kwargs.items():
                if (key in annotations and type(val) is not annotations[key]):
                    return default

            return decorated(*args, **kwargs)

        return decorator

    return get_decorator

데코레이터를 활용해서 이렇게 구현했음

@type_checker(((1, "잘못된 데이터"), None))
def send_message_api(session, phone_number: str):

이건 예시

 

2. Import All

파이썬에서 폴더를 모듈화 시키고 안에 있는 모든 함수들을 import할때 사용하려고 했음

from .operation import *
from .operation import 변수
from .operation import 함수
from .operation import 클래스

주로 이렇게 사용한다.

 

하지만 testing 폴더에 __init__.py를 생성하고

from .operation import *    # 현재 패키지의 operation 모듈에서 모든 변수, 함수, 클래스를 가져옴
from .geometry import *     # 현재 패키지의 geometry 모듈에서 모든 변수, 함수, 클래스를 가져옴

이렇게 작성해준다.

 

그럼 이제 다른 곳에서는 

import testing    # testing 패키지만 가져옴
 
print(testing.add(10, 20))   # 패키지.함수 형식으로 operation 모듈의 add 함수 사용
print(testing.mul(10, 20))   # 패키지.함수 형식으로 operation 모듈의 mul 함수 사용
 
print(testing.triangle_area(30, 40)) # 패키지.함수 형식으로 geometry 모듈의 triangle_area 함수 사용
print(testing.rectangle_area(30, 40))# 패키지.함수 형식으로 geometry 모듈의 rectangle_area 함수 사용

이렇게 testing만 import해서 하위에 있는 모든 것들을 import 가능함

 

그리고 __init__.py에서 

__all__ = ['add', 'triangle_area']    # calcpkg 패키지에서 add, triangle_area 함수만 공개

이렇게 해주면 모든 것을 공개하는게 아니라 add와 triangle_area만 공개할 수 있음

 

 

참고 : https://dojang.io/mod/page/view.php?id=2450 

 

파이썬 코딩 도장: 45.4 패키지에서 from import 응용하기

지금까지 calcpkg 패키지의 모듈을 가져올 때 import calcpkg.operation처럼 import 패키지.모듈 형식으로 가져왔습니다. 그러면 import calcpkg처럼 import 패키지 형식으로 패키지만 가져와서 모듈을 사용할 수

dojang.io

https://umbum.dev/176

 

[python] import 관련 : 모듈, 패키지, __init__.py, __all__

모듈을 싱글턴 처럼 쓸 수는 있지만 이렇게 쓰는건 별로다. 파이썬 모듈은 참조된 횟수에 상관없이 단 하나의 복사본만 불러온다. 따라서 모듈 자체를 하나의 싱글턴으로 사용할 수 있다. 그래

umbum.dev

https://nesoy.github.io/articles/2018-07/Python-init-all

 

Python의 __init__, __all__ 란?

 

nesoy.github.io

 

Q1.  ArrayList와 LinkedList를 설명하세요.

 

A1. 

ArrayList는 조회가 빠르고, LinkedList는 삽입, 삭제가 빠름

ArrayList는 dynamic array기반, LinkedList는 doubly linked array 기반임

LinkedList는 뒤의 값을 저장할 추가공간이 필요하다

 

모범답안. 


 

Q2. [Java] Exception, Error의 차이에 대해서 설명하세요.

 

A2.

에러는 복구 불가능 / exception은 try/catch를 통해 복구 가능

 

모범답안.

 



참조 : https://github.com/brave-people/brave-tech-interview/blob/main/contents/language.md

 

GitHub - brave-people/brave-tech-interview: 🙋 핵심을 질문하다. 그리고 용감하게 대답하다. 국내 IT기업부

🙋 핵심을 질문하다. 그리고 용감하게 대답하다. 국내 IT기업부터 실리콘밸리까지 "현직자가 해설해주는 기술면접" - GitHub - brave-people/brave-tech-interview: 🙋 핵심을 질문하다. 그리고 용감하게 대

github.com

 

Q1.  동기, 비동기에 대해 설명하고 장단점을 각각 설명해보세요.

 

A1. 

동기 -> 프로그램이 순차적으로 진행됨, 안정적이고 속도가 느림 -> 어려운 언어들..

비동기 -> 기다려주지 않고, 일단 순서대로 모두 진행함, 속도가 빠르지만, 처리하기 까다로움 -> 대부분 언어들 JS, python, java

 

모범 답안.

동기 -> Call 하고 응답이 올때까지 기다렸다가 다음 로직을 실행한다.

비동기 -> Call 하고 응답이 오지 않아도 다음 로직을 실행한다.


 

Q2. HashMap 동작 방식에 대해서 설명하세요

 

A2.

한개의 Key에 대해서 1개의 대칭됨. 검색할때 O(1)이 걸림

 

모범답안.

객체를 Map에 넣음 -> 여기서 객체란 Key-Value쌍을 넣음

Key는 유니크해야됨

동일하지 않은 두 객체가 같은 위치에 들어가려고 하는 경우 Collision

 


 

Q3. Array vs List vs Vector의 차이점

 

A3.

Array -> 추가 삭제가 용이

List -> 리스트 -> 검색이 용이함

Vector -> 잘모르겠음

 

모범답안.

Array (배열)

크기가 정해져 있다 / 기능이 없다.

길이를 바꿀 수 없다.

 

List(리스트)

배열이 가지고 있는 인덱스라는 장점을 버리고 빈틈없는 데이터의 적재

엘리먼트들 간의 순서가 중요함 -> 몇번째 데이터 인가

크기를 추가하기 편함

데이터 갯수가 확실하게 정해져있고, 자주 사용되면 array가 나음

https://wayhome25.github.io/cs/2017/04/17/cs-18-1/

 

Vector (벡터)

연속적인 메모리

미래에 들어갈 요소들을 위해 선할당을 한다.

끝에 추가하는 것은 O(1), 다른곳은 O(n)

랜덤하게 vector요소에 접근 가능

https://theemeraldtablet.tistory.com/entry/list%EC%99%80-vector-%EC%B0%A8%EC%9D%B4%EC%A0%90


참조 : https://github.com/brave-people/brave-tech-interview/blob/main/contents/language.md

 

GitHub - brave-people/brave-tech-interview: 🙋 핵심을 질문하다. 그리고 용감하게 대답하다. 국내 IT기업부

🙋 핵심을 질문하다. 그리고 용감하게 대답하다. 국내 IT기업부터 실리콘밸리까지 "현직자가 해설해주는 기술면접" - GitHub - brave-people/brave-tech-interview: 🙋 핵심을 질문하다. 그리고 용감하게 대

github.com

 

Q1.  Dynamic Programming이란? 장점은?

 

A1. 이전의 결과값들을 저장해서 처리 속도를 향상시키는 프로그래밍 기법 ex) 피보나치


 

Q2. map, hashmap, set에 대해서 설명하세요

 

A2.

Hash의 정의 : 특정 input값을 주어지면 항상 동일값을 보장해주는 것

 

Map의 정의 : 기본적으로, put과 get을 가지고 있는 인터페이스로, 추가하고, 값을 가져 올 수 있는 인터페이스

종류로는 HashMap, TreeMap, LinkedHashMap이 있다.

 

HashMap의 정의 : Hash 형식을 가지고 있는 key-value의 Map

 

Set의 정의 : array나 list처럼 순열 자료구조. but 순서라는 개념이 존재하지 않음. 보통 해쉬값 기반으로 저장함

 

**HashTable은 HashMap과 비슷한 Collection이지만, Thread-safe한 특징이 있다.

https://gompangs.tistory.com/entry/Hashtable%EC%97%90-%EA%B4%80%ED%95%B4%EC%84%9C?category=537219 

 

Hashtable에 관해서

개요 HashMap과 비슷한 Collection이지만, Thread-safe 한 특징이 있다. Thread-safe 하게 동작을 보장하려면 여러가지 방법이 있지만, 그 중 가장 성능이 안좋은 synchronized block을 통해 객체 lock을 걸어 동..

gompangs.tistory.com


 

Q3. 배열의 최대값 / 최솟값 을 구하세요

 

A3. 코드상으로, max와 min을 저장해두고 한개씩 값을 비교해보면서 저장 -> 시간복잡도 O(n), 공간복잡도 O(1)

 

더 빠른 방법 - 2개씩 보기

def optimization_find_small_and_largest_number_in_array(A):
    _max = _min= A[0]

    for idx in range(0, len(A), 2):
        first = A[idx]
        second = A[idx + 1]
        if first < second:
            if first < _min: _min = first
            if second > _max: _max = second
        else:
            if second < _min: _min = second
            if first > _max: _max = first
    return _max, _min

 


참조 : https://github.com/brave-people/brave-tech-interview/blob/main/contents/algorithm.md

 

GitHub - brave-people/brave-tech-interview: 🙋 핵심을 질문하다. 그리고 용감하게 대답하다. 국내 IT기업부

🙋 핵심을 질문하다. 그리고 용감하게 대답하다. 국내 IT기업부터 실리콘밸리까지 "현직자가 해설해주는 기술면접" - GitHub - brave-people/brave-tech-interview: 🙋 핵심을 질문하다. 그리고 용감하게 대

github.com

 

+ Recent posts