코딩인터뷰 완전분석 (게일 라크만 맥도웰)

 

 

 

01. 배열과 문자열

문제 1.2

순열 확인 : 문자열 두 개가 주어졌을 떄 이 둘이 서로 순열 관계에 있는지 확인하는 메서드를 작성하라.

풀어보기

순열 관계라는 것은 두 문자열에서 사용된 문자는 같은데 문자의 순서만 다른 형태라는 것을 의미한다.

 

1. 정렬 후 리스트 비교

먼저 두 문자열의 길이가 같은지 확인한다. 길이가 다르면 순열 관계가 아니라고 판단한다.

길이가 같다면 두 문자열을 정렬하여 두 개의 리스트가 같은지 비교연산자를 통해 비교한다.

# 1.2 순열 확인

def istnsduf(str1, str2):
    if len(str1) == len(str2):

        listStr1 = list(str1)
        listStr2 = list(str2)
        listStr1.sort()
        listStr2.sort()

        if listStr1 == listStr2:
            return True
    return False

print('ABC', 'AER', istnsduf('ABC', 'AER'))
print('CBS', 'SCB', istnsduf('CBS', 'SCB'))

# -결과----------------------------------------------------------------------------------
# ABC AER False
# CBS SCB True

모법답안

먼저 확인 해야 할 사항은. 대소문자는 구별할 것인지? 그리고 공백은 어떻게 볼 것인지?

여기서는 대소문자를 구별하고 공백을 하나의 문자열로 판단하기로 한다.

 

 

1. 정렬하여 비교하기

순열 관계의 문자열은 정렬하면 같은 문자열이 되기 때문에 정렬 후 두 문자열을 비교해주면 된다. 단순하고 이해하기 쉽다는 측면에서 좋은 풀이이지만, 효율성 측면에서는 최적은 아니다.

 

 

2. 문자열에 포함된 문자의 출현 횟수가 같은지 비교

순열 관계의 문자열은 동일한 문자가 동일한 횟수로 출현한다는 특징이 있다. 이를 각각 문자열에서 기록하고 이 횟수를 비교한다

1번 풀이는 O(NlogN) 의 시간 복잡도, 2번 풀이는 O(N)의 시간 복잡도가 걸릴 것 같다!

패리티 비트(parity bit)란 정보의 전달 과정에서 오류 발생 여부를 검사하기 위해 추가된 비트이다. 전송하고자 하는 데이터의 끝에 1비트를 더하여 송수신 하는 방식으로 사용한다.

패리티 비트의 종류는 전송하고자 하는 데이터에 포함된 1의 개수에 따라서 짝수 패리티와 홀수 패리티, 2가지가 있다.


예를 들어 ASCII코드 A 를 나타내는 1000001 을 전송하고자 할 때,

홀수 패리티를 사용한다면 1000001 + 1 (1의 개수가 총 3개로 홀수를 맞춰 준다)

짝수 패리티를 사용한다면 1000001 + 0 (1의 개수가 총 2개로 짝수를 맞춰 준다)


송신 호스트는 다음과 같은 방식으로 데이터를 전송한다. 이때 수신 호스트도 7비트까지의 데이터를 보고 패리티 검사 방식(짝수, 홀수)에 따라 패리티 비트를 계산한 결과와 실제 받은 데이터 값을 비교하고 값이 같다면 오류가 없다고 판단하고, 값이 다르다면 오류가 있다고 판단하는 방식이다. 이렇게 오류가 있는 데이터를 받았을 경우에는 송신 측에 다시 데이터를 요청하는 방식으로 안정적인 통신을 할 수 있게 해주는 장치이다.

패리티 비트의 한계점

하지만 패리티 비트는 오류를 검사만 할 수 있을 뿐, 수정하지 못한다는 한계점을 가지고 있다. 그리고 만약 두 개의 비트가 오류 전송 될 경우 데이터는 서로 다르지만 같은 패리티 비트를 가지기 때문에 이 때는 오류를 제대로 검사할 수 없다. 즉 오류 비트가 홀수 개일 경우에만 오류를 검사할 수 있다는 한계점이 있다.

병렬 패리티

이런 한계점을 보완하기 위해 패리티를 가로 세로로 구성되는 데이터 블록에 적용하여 에러 위치를 찾아 정정할 수 있도록 만든 것이 병렬 패리티이다.

병렬 패리티는 아래 표에서와 같이 각각의 가로 1바이트에 대해 패리티를 만들고 각각의 세로 1바이트에 대해 패리티를 구성하여 블록 단위로 전송하면 가로와 세로에 대해 각각 패리티를 검사함으로써 에러를 찾아내고 정정할 수 있다.

전송된 데이터 블록 중에서 한 비트의 에러가 발생하면 가로와 세로 패리티의 특정 부분에 패리티가 맞지 않게 되며 아래 표에서와 같이 두 부분이 마주치는 곳에서 에러가 발생함을 알 수 있음에 따라 이를 정정할 수 있다.

참고문헌: '디지털 논리회로 이해', 오창환 저, 한국학술정보(주)

참고문헌: '디지털 논리회로 이해', 오창환 저, 한국학술정보(주)

코딩인터뷰 완전분석 (게일 라크만 맥도웰)

 

 

 

01. 배열과 문자열

문제 1.1

중복이 없는가 : 문자열이 주어졌을 때, 이 문자열에 같은 문자가 중복되어 등장하는지 확인하는 알고리즘을 작성하라. 자료구조를 추가로 사용하지 않고 풀 수 있는 알고리즘 또한 고민하라.

풀어보기

1. 집합(SET) 자료형을 사용한다.

집합 자료형의 특성은 중복을 허용하지 않는다. 따라서 주어진 문자열을 집합 자료형으로 변환하여 최초 문자열의 길이와 변환된 집합 자료형의 길이를 비교한다. 길이가 늘어나는 것은 불가능하고 길이가 같다면, 중복이 없는 것이고 길이가 줄어들었다면 중복된 문자열이 제거된 만큼 길이가 줄어든 것이므로 중복된 문자열이 등장한 것이다.

# python
str = 'absas'    # 문자열 선언
def isUniqueChar(str):    # 중복된 문자열이 있으면 False, 중복되지 않고 유니크하다면 True
    str_set = set(str)    # 문자열을 집합 자료형으로 변환
    if len(str) == len(str_set):
        return True
    else:
        return False

print('naver', isUniqueChar('naver'))
print('kakao', isUniqueChar('kakao'))

# ----------------------결과--------------------------------------------------------------
# naver True
# kakao False

2. 각 문자를 순차적으로 다른 문자들과 비교한다.

문자열의 0번째 문자를 1부터 n번째 문자열과 순차적으로 비교한다. 그리고 1번째 문자를 2부터 n번째 문자열과 비교한다. 이런식으로 (n-1)~n번째 까지 반복하여 같은 문자열이 나오는 즉시 중복이 있는 문자열로 판단한다. 시간 복잡도는 O(N^2). 문제에서 요구한 자료구조를 추가로 사용하지 않고 풀 수 있는 알고리즘

# python
def isUniqueChar(str):     # 중복된 문자열이 있으면 False, 중복되지 않고 유니크하다면 True
    for i in range(len(str)):
        if str[i] in str[i+1:]:    # 중복된 것 있는지 확인
            return False
    return True
print('naver', isUniqueChar('naver'))
print('kakao', isUniqueChar('kakao'))

# ---------------------결과--------------------------------------------------------------
# naver True
# kakao False

모법답안

먼저 문자열이 ASCII 문자열인지 유니코드 문자열인지 확인 하는 센스. 이에 따라 저장 공간 크기가 달라질 수 있다. 일단 문자열이 아스키 코드 라고 가정했을 때 풀이. 아스키코드와 유니코드 이해

 

아스키코드와 유니코드 (ASCII, Unicode)의 이해

비트와 바이트 아스키코드와 유니코드를 이해하기 위해서는 먼저 비트와 바이트의 개념부터 알아야한다. 컴퓨터는 정보를 표현하기 위해 전기 신호를 주고받는다. 전기 신호가 있으면 1, 없으

kih0902.tistory.com

 

 

 

1. 표현 가능한 범위만큼 배열을 선언하여 배열의 인덱스에 접근하는 횟수를 통해 중복을 판단한다.

코드의 시간 복잡도는 O(N). N은 문자열의 길이. 하지만 아스키 코드가 표현 가능한 갯수를 초과하여 순회하지 않기 때문에 O(1)이라고 볼 수도 있다.

boolean isUniqueChars(String str) {
    if (str.length() > 128)
    {
        return false;    // 아스키 코드 문자의 개수 128. 이를 넘어가면 반드시 중복이 발생한다.
    }
    boolean[] char_set = new boolean[128];    // 128길이의 배열 선언

    for(int i = 0; i < str.length(); i++)    // 문자열의 길이만큼 반복
    {
        int val = str.charAt(i);    // i번째 문자열의 아스키 코드 값을 val변수에 저장
        if (char_set[val] == true)
        {
            return false;    // 현재 문자열과 같은 아스키코드를 가진 문자가 이미 존재했었다.
        }
    }
    return true;    // 겹친 것이 하나도 없다면 
    }

 

2. 비트벡터를 사용

비트벡터를 사용하여 문자열 중복 판단하기

 

Shortcut Keys

Summary Frequently Used Shortcut Keys Autocomplete File Edit Paragraph Format View Change Shortcut Keys macOS Windows / Linux Q: Shortcut keys does not work on Ubuntu Summary You can use shortcut keys to quickly insert or modify styles or do other operatio

support.typora.io

 

 

3. 문자열을 정렬한 뒤 인접한 문자열을 비교하는 방식으로 판단한다.

정렬을 할 때 O(nlogn)의 시간이 소요된다. 정렬 할 때 많은 알고리즘이 공간을 추가로 사용한다는 것도 기억해라. 문제에서 요구한 자료구조를 추가로 사용하지 않고 풀 수 있는 알고리즘

The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.

화면을 실행 시 아래와 같은 오류가 발생하는 경우 에러는 해결하는 방법을 알아보자.

원인

이 문제의 원인은 tomcat에서 호출한 경로를 제대로 인식하지 못해서 발생한다고한다.

해결 방법

1. tomcat의 module path를 변경한다.

  • 서버의 톰캣을 더블클릭후 Module 탭으로 들어간다.

  • Web Modules에 Path를 / 로 변경한다

2. 프로젝트 속성 - Web Project Setting에서 Context root를 변경한다.

Tomcat localhost:8080 접속시 인증 문제 해결

톰캣을 실행 후 로컬호스트로 jsp 페이지를 접속하려고 하니 아래와 같은 웬 로그인 창이 뜨면서 접속이 안 되는 경우가 있다.

원인

이 문제의 원인은 oracle DB를 사용하는 경우 톰캣의 포트와 포트 번호가 충돌이 생겨서 발생하는 오류이다.

해결 방법

해결 방법은 오라클 포트를 변경하던지, 톰캣의 기본포트를 변경하던지 둘 중 하나를 변경하면 된다. 여기서는 톰캣의 포트를 변경해보겠다.

  • 톰캣이 설치되어 있는 아래 경로로 들어간다

    C:\Program Files\Apache Software Foundation\Tomcat 8.5\conf

  • 해당폴더에서 server.xml파일을 찾아 포트를 변경해준다

    <Connector port="8888" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />

문제 설명

1. N 개의 정수를 가진 리스트 A와 정수 K가 입력으로 주어진다.
2. 문제의 목표는 A리스트를 K번 회전한 결과 리스트를 리턴하는 것.
3. 회전이란 리스트의 모든 요소가 하나씩 오른쪽으로 이동하는 것을 말한다(마지막 요소는 첫번째로 이동)

 

 

풀면서 주의할 점은 예외케이스를 놓치지 않는 것이다. 

 

 

입력으로 빈 리스트가 주어지거나 

리스트는 입력 됬는데 회전 횟수가 0으로 입력되는 경우를 처음에 생각못해서 헤맸다...  

 

 you can write to stdout for debugging purposes, e.g.
# print("this is a debug message")

def solution(A, K):
    # write your code in Python 3.6
    if len(A) == 0:	## 빈 리스트가 입력으로 들어올 수 있다.
        return []
    if K == 0:		## 리스트만 입력되고 회전 수가 0으로 주어질 수 있다.
        return A
        
    while K > 0:
        
        result = []
        for i in range(len(A)):
            if i == 0:
                result.append(A[-1])
            else:
                result.append(A[i-1])
        A = result
        K -= 1
    return result
    pass

 

 

 

Test results - Codility

An array A consisting of N integers is given. Rotation of the array means that each element is shifted right by one index, and the last element of the array is moved to the first place. For example, the rotation of array A = [3, 8, 9, 7, 6] is [6, 3, 8, 9,

app.codility.com

 

Codility 사이트에서 문제를 풀어보았다.

 

영어로 된 문제에 처음부터 당황..

 

하지만 수많은 예시들 덕분에 이해하는데 어렵진 않았다.

 

 

 

 

Test results - Codility

A binary gap within a positive integer N is any maximal sequence of consecutive zeros that is surrounded by ones at both ends in the binary representation of N. For example, number 9 has binary representation 1001 and contains a binary gap of length 2. The

app.codility.com

 

 

파이썬 알고리즘 공부를 하면서 여러가지 유용하고, 헷갈리는 문법들 정리

 

 

#1 시간, 공간 복잡도 관련 팁

 

알고리즘 수행시간을 알아보기 위한 코드

import time
start_time = time.time()

# 프로그램 작성

end_time = time.time()
print("time :", end_time - start_time)

- pypy3는 파이썬3의 문법을 그대로 지원하며, 대부분 파이썬3보다 실행 속도가 더 빠르다. Pypy3를 지원하는 환경이라면 속도를 줄이기 위해 이를 이용하도록 하자

 

- 기업코딩 테스트 환경에서는 파이썬으로 제출한 코드가 1초에 2000만번 연산을 수행한다고 가정하면 크게 무리가 없다.

 

- 시간제한이 1초인 문제를 만났을 경우 (참고만 하세요)

N의 범위  최소 시간 복잡도
500 O(N^3)
2,000 O(N^2)
100,000 O(NlogN)
10,000,000 O(N)

 

- 일반적으로 탐색해야할 전체 데이터의 개수가 100만개 이하일 때 완전탐색을 사용하면 적절하다.

 

- 정수형 자료형 데이터의 개수에 따른 메모리 사용량

데이터의 개수(리스트의 길이) 메모리 사용량
1,000 약 4KB
1,000,000 약 4MB
10,000,000 약 40MB

 

 

#2 입출력

 

공백을 기준으로 입력받기

# 3 3 3     <-- 변수로 저장
n, m, k = map(int, input().split())

# 2 4 5 2 3 <-- 배열로 저장
data = list(map(int, input().split()))

 

2차원 배열 입력받기

data = []
for i in range(n):
    # 데이터가 공백없는 형태로 입력될 때
    # 12345 --> [1, 2, 3, 4, 5]
    data.append(list(map(int, input())))
    
    # 데이터가 공백을 두고 입력될 떄
    # 1 2 3 4 5 --> [1, 2, 3, 4, 5]
    data.append(list(map(int, input().split())))

 

빠르게 입력받기 (일반적인 입력 방식보다 더 효율적)

import sys

data = sys.stdin.readline().rstrip()

 

f-string (더 간결하게 여러 자료형을 한 줄로 출력할 수 있음)

num = 7
print(f"정답은 {num}입니다.")

 

 

 

#3 정렬
#0 내림차순 정렬
B.sort(reverse=True) # 내림차순정렬

#1 튜플리스트, 2차원리스트일 경우 여러 가지 기준으로 정렬하기.
s_list.sort(key = lambda x : (-x[1], x[2], -x[3], x[0]))

#2 튜플에 숫자형과 문자형이 섞여있을 경우 숫자형에 int()를 씌워주면
# bad operand type for unary -: 'str' 이슈를 해결할 수 있다
s_list.sort(key = lambda x : (-int(x[1]), int(x[2]), -int(x[3]), x[0] ))

#3 리스트에서 median 값 구하는 식
data[(n-1) // 2] # n은 리스트 길이

#4 sorted with key
array = [('홍길동', 35), ('이순신', 75), ('아무개', 50)]
result = sorted(array, key = lambda x: x[1])
# 성적을 기준으로 오름차순정렬


#5 문자열, 배열, 튜플 등을 역순으로 출력(간결하게)
s = 'abcde'
print(s[::-1])  # 'edcba'
print(s[3:0:-1])  # dcba, 0~3인덱스를 역순으로

l = ['a', 'b', 'c', 'd', 'e']
print(l[::-1])  # ['e', 'd', 'c', 'b', 'a']
t = ('a', 'b', 'c', 'd', 'e')
print(t[::-1])  # ('e', 'd', 'c', 'b', 'a')

 

 

#4 문자열, 배열 다루기

 

파이썬 문자열 아스키변환

주요 아스키 코드값 0 ~ 9 : 48 ~ 57 , A ~ Z : 65 ~ 90, a ~ z : 97 ~ 122

ord('a') ## 아스키코드 숫자 반환
chr(ord('a')) ## 아스키코드에 해당하는 문자 반환

 

 

크기가 N이고 모든 값이 0인 리스트 초기화

N = 10
arr = [0] * N

 

1부터 10까지 증가하는 리스트 초기화

array = [i for i in range(1, 11)]

 

 

2차원 배열 좌표 이동

## 풀이 - 좀더 간단한 코드로

n = int(input())
x, y = 1,1
plans = input().split()

## L, R, U, D
dx = [0, 0, -1, 1]
dy = [-1,1,  0, 0]
move = ['L', 'R', 'U', 'D']

for plan in plans:
    for i in range(len(move)):
        if plan == move[i]:
            nx = x + dx[i]
            ny = y + dy[i]
    if nx < 1 or ny < 1 or nx > n or ny > n:
        continue
    x, y = nx, ny
print(x, y)

 

2차원 배열 90도 회전

n = len(a) # 행 길이 계산
m = len(a[0]) # 열 길이 계산
result = [[0] * n for _ in range(m)]
after = [] # 90도 회전된 배열 저장

# 시계방향으로 회전
for i in range(n):
	tmp = []
	for j in range(m):
    	tmp.append(before[m-1-j][i])
    after.append(tmp)
    
# 반시계방향으로 회전
for i in range(m):
    tmp  = []
    for j in range(n):
    	tmp.append(before[j][m-1-i]) #반시계

    after.append(tmp)

 

#5 자료형

- 1e9, 1E9 는 10의 9제곱과 같다.

- 임의의 큰 수를 표현하기 위해 자주 표현되는 형식

# 실수형의 계산은 정확하게 떨어지지 않는다.
# 반올림해서 사용하는 것을 습관화하자

if 0.3 + 0.6 == 0.9:
	print(True)
else:
	print(False)

# --> False

 

- 튜플은 한 번 선언되면 변경할 수 없다.

- 튜플은 리스트에 비해 공간 효율적이다.

 

 

#6 내장함수 및 라이브러리

 

eval() : 문자열로 표현된 수식의 계산 결과값을 반환

result = eval("(3+5)*7")
# --> 56

 

순열과 조합

# 순열 : 주어진 데이터를 가지고 서로 다른 n 개를 선택하여 일렬로 나열하는 것 
from itetools import permutations

data = [1, 4, 5, 6, 7]
result = list(permutations(data,3))

# 조합 : 주어진 데이터를 가지고 서로 다른 n 개를 선택하는 것 
from itetools import combinations

data = [1, 4, 5, 6, 7]
result = list(combinations(data,3))

 

Counter : 원소의 등장 횟수를 간단히 셀 수 있다, 원소와 등장 횟수를 사전 형태로 저장할 수 있다.

from collections import Counter

counter = Counter(['red', 'blue', 'green'])
print(dict(counter))

# --> {'red' : 1, 'blue' : 1, 'green' : 1}

마리아DB 최초 설치시 기본 포트 3306을 사용하려고 하니 다음과 같이 이미 포트가 사용 중이라는 오류가 발생했다.

 

원인은 언젠가 이 컴퓨터에 mysql이 설치 되어 있었던 것. . (mariaDB는 mysql과 거의 같다고 보면되는데 TCP포트도 같은 것을 사용한다) 

 

 

마리아DB 설치시 포트 중복에러

 

 

해결방법

1.  작업관리자 - 리소스 모니터를 열어 네트워크 (수신대기포트) 에서 3306 포트를 사용중인 것을 찾는다.

 

 

 

2. 위의 PID 번호를 기억

3. 윈도우 cmd 창을 관리자 권한으로 실행

 

 

4. taskkill /F /PID(아까 기억한 PID)

5. 다시 같은 포트로 mariDB 설치

 

설치완료~~



시간 제한메모리 제한제출정답맞은 사람정답 비율
2 초128 MB105655229405051.770%

문제

조세퍼스 문제는 다음과 같다.

1번부터 N번까지 N명의 사람이 원을 이루면서 앉아있고, 양의 정수 M(≤ N)이 주어진다. 이제 순서대로 M번째 사람을 제거한다. 한 사람이 제거되면 남은 사람들로 이루어진 원을 따라 이 과정을 계속해 나간다. 이 과정은 N명의 사람이 모두 제거될 때까지 계속된다. 원에서 사람들이 제거되는 순서를 (N, M)-조세퍼스 순열이라고 한다. 예를 들어 (7, 3)-조세퍼스 순열은 <3, 6, 2, 7, 5, 1, 4>이다.

N과 M이 주어지면 (N,M)-조세퍼스 순열을 구하는 프로그램을 작성하시오.

입력

첫째 줄에 N과 M이 빈 칸을 사이에 두고 순서대로 주어진다. (1 ≤ M ≤ N ≤ 5,000)

출력

예제와 같이 조세퍼스 순열을 출력한다.

예제 입력 1 

7 3

예제 출력 1 

<3, 6, 2, 7, 5, 1, 4>

  

   


<풀이과정>



큐를 이용해서 1부터 n까지 만들고 


원을 이루면서 돌아가는 것을  


큐에서 첫 번째를 뽑아서 다시 맨 뒤에 넣는 방식으로 설계 


항상 첫번 째를 가리키고 한 칸씩 움직이는 것을 m-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
// n,m을 입력받는다. 
// 1~n까지 번호를 만들고 n다음에 다시 1이 오도록 한다. 
// m번째 번호를 순차적으로 제거하고 제거된 번호를 제거된 순서대로 저장한다. 
// 제거된 순서대로 번호를 출력한다. 
 
#include<iostream>
#include<queue>
using namespace std;
int main(){
    int n,m;
    queue<int> q;
    
    cin >> n >> m; // 숫자 입력 
    
    for(int i=1;i<=n;i++){
        q.push(i); // 1부터 n까지 차례대로 q에 넣는다. 
    }
    cout << "<";
    while(n--){ // n번 반복
        for (int i=1;i<m;i++// m-1번 반복 
        {
            q.push(q.front());
            q.pop();
            // 1번 1,2,3,4,5,6,7 -> 2,3,4,5,6,7,1 
            // 2번 2,3,4,5,6,7,1 -> 3,4,5,6,7,1,2 
        }
        cout << q.front(); // 3을 출력
        q.pop(); // 4,5,6,7,1,2
        if(n!=0){
            cout <<", ";
        }    
    }
    cout << ">";
    return 0;
}
cs



정답~!


+ Recent posts