1. 중복순열

1~n의 숫자 중 m개를 중복순열로 선택하기

n개의 노드를 가진 트리를 m레벨 만큼 내려가며 1에서 n사이의 숫자를 중복하여 선택한다

 

import sys
input=sys.stdin.readline #input 속도 개선/ 문자열 읽을 시 input().rstrip()으로 개행문자 제거필수
#중복순열
def dfs(lev): 
    global cnt
    if lev==m:
        print(res)
        cnt+=1

    else:
        for i in range(1,n+1): #1~n까지 m번 돌면서 하나씩 선택
            res[lev]=i
            dfs(lev+1)


if __name__=="__main__":
    n,m = map(int,input().split()) #n개 중 m개 중복순열 > n개의 노드 트리 m개 레벨 생성
    res=[0]*m
    cnt=0
    dfs(0)
    print(cnt) #중복순열의 개수

실행결과

 

 

2. 순열

순열은 중복순열과 로직이 거의 똑같다.

단, dfs를 태울때 중복으로 선택하지 않도록 체크해주면 된다.

 

import sys
input=sys.stdin.readline #input 속도 개선/ 문자열 읽을 시 input().rstrip()으로 개행문자 제거필수
#순열
def dfs(lev):
    global cnt
    if lev==m:
        print(res)
        cnt+=1

    else:
        for i in range(1,n+1): #1~n까지 m번 돌면서 하나씩 선택
            if(ch[i]==0):   #선택하지 않은것만
                res[lev]=i  #선택
                ch[i]=1     #체크
                dfs(lev+1)
                ch[i]=0


if __name__=="__main__":
    n,m = map(int,input().split()) #n개의 노드 트리 m개 레벨 생성
    res=[0]*m
    ch=[0]*(n+1) #중복 제외처리 체크배열
    cnt=0
    dfs(0)
    print(cnt) #순열의 개수

실행결과

 

 

3. 조합

조합은 1~n의 숫자들 중 m개를 선택한 부분집합끼리도 중복이 없어야 한다. [2,4]=[4,2]

n개의 숫자중 하나씩 택할때마다 다음 노드는 무조건 앞에서 선택한 것보다 큰 수를 선택하도록 한다. (중복방지)

 

import sys
input=sys.stdin.readline #input 속도 개선/ 문자열 읽을 시 input().rstrip()으로 개행문자 제거필수
#조합
def dfs(lev,node):
    global cnt
    if lev==m:
        print(res)
        cnt+=1

    else:
        for i in range(node,n+1): #node~n까지 m번 돌면서 하나씩 선택
            res[lev]=i
            dfs(lev+1, i+1) #트리 가지에 +1 (중요)

if __name__=="__main__":
    n,m = map(int,input().split()) #n개의 노드 트리 m개 레벨 생성
    res=[0]*m
    cnt=0
    dfs(0,1)
    print(cnt) #조합의 개수

실행결과

 

 


참고

 
반응형

1. 부분집합

1부터 N까지의 부분집합을 구할때 DFS로 부분집합을 구현할 수 있다.

집합 원소는 포함할 수, 포함하지 않을 수로 체크하는 배열을 두어서 구현한다.

DFS가 N+1까지 도달하면 포함하기로 한 수를 차례로 출력한다.

 

#부분집합
def dfs(v):
    if v==n+1: #도착점
        for i in range(1,n+1):
            if ch[i]==1: print(i, end=' ')
        print()

    else:
        ch[v]=1 #사용하겠다
        dfs(v+1)
        ch[v]=0 #사용안함
        dfs(v+1)


if __name__=="__main__":
    n=int(input())
    ch=[0]*(n+1)
    dfs(1)

실행결과

 

 

2. 합이 같은 부분집합 (응용)

입력받은 배열의 합과 부분집합의 합의 차이를 이용한다. (total-sum)

사용할 원소는 해당 원소를 더해준다.

사용하지 않을 원소는 기존 sum 값을 유지하고 트리 레벨만 증가시킨다.

 

import sys

def dfs(lev,sum): #tree level
    if sum>total//2: return #cut off (합이 같은 부분집합이므로 절반 이상 합산은 제거)

    if lev==n: #dfs탈출
        if sum==(total-sum):
            print("합이같은 부분집합 존재 : ",sum)
            sys.exit(0)

    else:
        dfs(lev+1, sum+arr[lev]) #사용
        dfs(lev+1, sum)          #사용x (기존 sum 그대로)

if __name__=="__main__":
    n=int(input())
    arr=list(map(int,input().split()))
    total=sum(arr)
    dfs(0,0)

    print("합이 같은 부분집합 없음") #dfs 함수에서 종료처리 안됐을 시

실행결과

[1,3,5,7] [6,10] 16으로 합이 같은 부분집합이 존재한다.

 

 

 

 

 


참고

 

파이썬 알고리즘 문제풀이 입문 (코딩테스트 대비) - 인프런 | 강의

파이썬(Python)을 이용해 코딩 테스트 문제 풀이를 합니다., - 강의 소개 | 인프런...

www.inflearn.com

 

반응형

JAVA의 메모리 영역 <메소드/스택/힙>

  • 메소드 : 바이트 코드, 전역변수, static변수
  • 스택 : 매개변수, 지역변수 (사용 종료 시 바로 소멸, 컴파일 시 메모리 할당)
  • 힙 : new로 생성된 객체 (호출 끝나도 사라지지 않음, 프로그램 실행 시 동적할당) 

자바 프로그램 실행과정

1) JVM : OS로부터 프로그램이 필요로 하는 메모리 할당받음
2) javac (자바 컴파일러)가 소스코드(.java)를 읽어 바이트코드(.class)로 변환시킴 (컴파일)
3) 클래스로더 : class 파일들 JVM으로 로딩
4) 실행엔진 : 로딩된 class 파일들 해석 (class 실행)
5) 해석된 바이트코드 > 런타임 데이터 영역에 배치 (실질적 수행)

위 과정 중에 JVM은 GC작업 수행 (스레드 동기화 등)

 

 

자바 프로그램 실행과정과 JVM 구성

JVM (자바 가상 머신)

JAVA가 OS에 구애받지 않고 재사용 가능하게 함 (중개자 역할 : JAVA - JVM - OS )

자바 애플리케이션을 클래스 로더로 읽어 자바 API와 함께 실행 (스택기반 가상머신)

역할 : 메모리관리, 가비지 컬렉션

 

JVM 구성

1) 클래스로더 : JVM으로 클래스파일 로드, 링크를 통해 배치, 런타임 시 동적으로 클래스 로드, 컴파일러 역할


2) 실행엔진 : 클래스로더가 런타임 영역에 배치한 바이트코드를 실행 가능한 형태로 변경, 실행

  • 인터프리터 : 한 줄씩 수행 (느림)
  • JIT (just-in-time) : 인터프리터 방식으로 실행하다가 적절한 시점에 바이트 코드 전체 컴파일 > 네이티브 코드로 변경 > 네이티브 코드로 실행 (네이티브 코드 : 캐시 보관, 한 번 컴파일된 코드 빠른 수행)
  • 네이티브 코드 : 자주 수행되는 메소드를 JVM->실행엔진->JIT 컴파일

3) 가비지 컬렉터 : 가비지 컬렉션

 

4) 런타임데이터영역 : JVM의 메모리영역. 자바 애플리케이션을 실행할 때 사용하는 데이터들을 적재하는 영역

  • 메소드 영역 : 모든 쓰레드가 공유하는 영역 (클래스, 인터페이스, 메소드, 필드, static 변수 등 바이트코드 보관)
  • 힙 영역 : 모든 쓰레드가 공유하는 영역 (new로 생성된 객체/배열. GC가 참조되지 않는 메모리를 제거하는 영역)
  • 스택 영역 : 메소드 호출 시마다 생성되는 영역 (메소드 내 매개변수, 지역변수 등을 임시로 저장. 메소드 끝날때 삭제)
  • PC 레지스터 : 쓰레드 시작될 때마다 각각 생성 (쓰레드가 어떤 명령을 실행할지 기록, 수행중인 JVM 명령의 주소를 가짐)
  • 네이티브 메소드 스택 : 자바 외 언어로 작성된 코드를 위한 영역

 

 

가비지 컬렉션 (GC)

가비지 정리 프로그램 (가비지 : 정리되지 않은 메모리, 유효하지 않은 메모리주소)

참조되지 않은 객체 해제, 가용 공간 만듦 > heap 메모리 재활용을 위해 

자동 메모리 정리로 개발자의 개발 속도 향상

 

*Mark : 스택의 모든 변수를 스캔, 각각 어떤 오브젝트를 레퍼런스 하고있는지 찾는 과정

*Sweep : Mark되지 않은 모든 오브젝트들을 heap에서 제거

 

문제점 : 메모리를 되찾을 시점을 결정하기 위한 오버헤드 발생 가능

 

 

JVM, JRE, JDK 구성도

 

JRE (Java Runtime Environment) : 자바 실행환경

JVM이 자바 프로그램을 동작시킬 때 필요한 라이브러리, 기타 파일들을 가지고 있음 

JVM + 자바 클래스 라이브러리 + 자바 명령(command) + 기타인프라를 포함한 디렉토리 (패키지)

  • bin/ : Java 실행 프로그램, JVM 시작하는 java (javaw,,), keytool, policytool 등
  • conf/ : 사용자가 편집가능한 파일 
  • lib/ : supporting 파일, .jar 구성파일, 속성, 글꼴, 인증서, .class 포함 모듈
  • 네이티브 바이너리 코드 지원 : .dill (Window), dylib (Mac), .so (Linux) 

 

JDK (Java Development Kit) : JRE+개발도구들 (javac, jdb, java, etc...)

Java용 SDK (Software Development Kit) => 프로그램 생성, 컴파일 가능

JRE의 상위 집합 디렉터리 세트 

  • bin/ : 개발도구로 확대 - javac (.jar, javadoc, jshell)
  • jmods/ 추가 

일반적으로 Java 프로그램 실행 = JRE만 있으면 됨. 

Java 프로그래밍 = JDK 설치 필요

 

애플리케이션 서버 = JSP 를 Java Servlet으로 변환 >> JDK를 사용해서 Servlet 컴파일 해야함

>>> JDK 설치 필요

 


Runtime Data Area

프로그램 수행을 위해 OS에서 할당받은 메모리 공간

Runtime Data Area

구성

1) PC : 프로그램 카운터 레지스터, 스레드 시작 될 때 생성됨. (1스레드 1PC) 현재 수행중인 JVM 명령 주소 가짐

2) JVM stack : 프로그램 실행 중 소멸되는 특성의 데이터 임시저장, 삭제 (임시 할당, 변수, 임시데이터, 스레드, 메소드 등)

3) Native Method stack : 실제 실행가능한 기계어 프로그램 실행 영역, JAVA 외의 언어로 작성된 코드를 바이트코드로 전환, 저장

4) Method Area (=Class area = Static area) : 클래스 정보를 처음 메모리 공간에 올릴 때 초기화되는 대상을 저장

    (Runtime Constant Pool : 상수 자료형 저장, 참조/ 중복 방지)

5) Heap : new연산으로 생성된 객체, 배열을 저장하는 가상 메모리 공간


*오버로딩과 오버라이딩

  • 오버로딩 : 메소드의 이름은 같고, 매개변수를 다르게 함으로써 여러 메소드를 만드는 것
  • 오버라이딩 : 부모클래스로부터 상속받은 메소드를 재정의하는 것. 자식 객체에서 오버라이딩한 메소드는 호출시 오버라이딩한 메소드가 우선시 되어 호출됨 (동일한 리턴타입, 메소드 이름, 매개변수를 가져야함)

*추상클래스와 인터페이스

  • 추상클래스 : 클래스 내에 추상 메소드가 하나 이상 포함되거나 abstract로 정의된 경우. extends를 통해 기능을 이용하고 확장하도록 하는 클래스
  • 인터페이스 : 모든 메소드가 추상 메소드인 경우 (여러 implements가 가능해 다중 상속 구현 가능) 뼈대만 있으며, 구현하는 모든 클래스에 대해 강제적으로 메소드를 구현하도록 만듬

*메모리, 성능 개선 방법

  • 인스턴스 변수에 접근할 일이 없으면, static 메소드를 선언하여 호출
  • 모든 객체가 서로 공유할 수 있기 때문에 메모리가 절약되고 연속적으로 그 값의 흐름을 이어갈 수 있는 장점이 존재

*클래스와 구조체의 차이

  • 구조체 : 여러 자료형의 변수들을 하나의 구조로 묶을 수 있는 자료구조.
  • 클래스 : 변수뿐만 아니라, 메소드도 포함시킬 수 있음
  • 구조체도 함수 포인터를 이용하면 클래스처럼 만들어 낼 수도 있다.

*스레드 생성, 장단점

  • 생성 : Runnable(인터페이스)로 선언되어 있는 클래스 or Thread 클래스를 상속받아 run() 메소드를 구현
  • 장점 : 빠른 프로세스 생성, 메모리를 적게 사용 가능, 정보 공유가 쉬움
  • 단점 : 데드락에 빠질 위험이 존재

*벡터와 배열

  • 벡터 : 동기식. 한 스레드가 벡터 작업 중이면 다른 스레드가 벡터 보유 불가능
  • 배열리스트 : 비동기식. 여러 스레드가 배열리스트에서 동시 작업이 가능

Reference

 

NAVER 기술 면접 리뷰

NAVER 기술 면접 질문과 답변을 정리합니다.

martianlee.github.io

 

 

gyoogle/tech-interview-for-developer

👶🏻 신입 개발자 전공 지식 & 기술 면접 백과사전 📖. Contribute to gyoogle/tech-interview-for-developer development by creating an account on GitHub.

github.com

 

 

#자바가상머신, JVM(Java Virtual Machine)이란 무엇인가?

#JVM이란? JVM이란 JAVA Virtual Machine, 자바 가상 머신의 약자를 따서 줄여 부르는 용어이다 (가상머신이란 프로그램의 실행하기 위해 물리적 머신과 유사한 머신을 소프트웨어로 구현한 것이다.) JV

asfirstalways.tistory.com

 

 

[ Java ] JDK, JRE 차이점(JDK란? JRE란?)

JDK와 JRE의 차이? JRE란? JRE( Java Runtime Environment )는 자바 가상 머신( Java Virtual Machine ), 자바 클래스 라이브러리( Java class library ), 자바 명령( Java command ) 및 기타 인프라를 포함한 컴..

developerntraveler.tistory.com

 

 

위키독스

온라인 책을 제작 공유하는 플랫폼 서비스

wikidocs.net

 

 

JVM 메모리 구조란? (JAVA)

안녕하세요? 코딩 중독입니다. 오늘은 JVM 메모리 구조에 대해 알아보겠습니다. JVM이란? JVM 메모리 구조를 설명하기 전에 JVM이 무엇인지 알아야 합니다. JVM은 Java Virtual Machine의 약자로, 자바 가상

steady-coding.tistory.com

 

반응형

리스트 생성

a = []  #기본

a = [0]*N #크기 N의 1차원 리스트를 0으로 초기화 생성

b = [[0]*N for _ in range(N)] #N*N 2차원 리스트를 0으로 초기화 생성

 

리스트의 입출력

연속 입력 시 input().split() 을 사용한다. 

input()은 기본적으로 문자열 형식으로 입력받기 때문에 다른 자료형으로 입력받으려면 map을 사용하면 된다.

#변수입출력
N = input() #기본적으로 문자열로 받음, 정수입력 = int(input())
a, b = map(int, input().split()) #int로 연속입력

#리스트입출력
arr = list(input().split()) #공백으로 구분, 연속입력
arr2 = list(map(int, input().split())) #int로 입력 

#리스트 원소 붙여서 출력
arr=''.join(arr)
print(arr)

#리스트 원소 사이의 문자 지정 가능
arr='.'.join(arr)
print(arr)


#2차원리스트입력
for i in range(n):
    arr3.append(list(map(int, input().split())))

arr4=[list(map(int, input().split())) for _ in range(n)]

a=''.join(a)

 

기본적으로 사용하는 메소드들

import random as r

b= list(range(1,11)) #1~10

r.shuffle(b) #b 무작위로 섞음 

b.insert(인덱스, 값) #해당 인덱스에 값 추가

b.append(값) #리스트 끝에 해당 값 추가

b.pop() #끝값 제거

b.remove(값) #첫번째 값 삭제
del b[인덱스] #해당 인덱스 값 삭제

b.index(값) #해당값의 인덱스 출력

len(b) #리스트 b의 길이

 

리스트 슬라이스 기능

a[:n] #0~(n-1)인덱스까지 슬라이스

 

enumerate 

리스트의 인덱스, 값에 각각 접근이 가능하다.

for x in enumerate(b):
	print(x) # len(b) 만큼 리스트 b의 (인덱스, 값)이 tuple형으로 순서대로 출력됨
	print(x[0], x[1]) #괄호, 콤마 없이 인덱스 값 만 출력됨
    
for index, val in enumerate(b):
	print(index, val) # line 3과 출력 같음

 

all, any

if all(50>x for x in a):
	print("모두 50 이상") 
    
if any(50>x for x in a):
	print("하나라도 50 이상")

 

 

python list 내장함수들에 대해 기본적으로 정리해보았고 계속해서 추가할 예정이다,,

반응형

sorted()

1. sorted()는 리스트, 문자, 숫자 모두 정렬이 가능하다 list 형으로 반환한다. (용도에 맞게 join 하기)

   ※ sort()는 리스트 자료형만!

 

2. key 옵션으로 정렬 기준을 지정할 수 있다. 

a = ['aaa', 'aa', 'b', 'cccc']
sorted(a, key=len) # ['b', 'aa', 'aaa', 'cccc']

b = ['cde', 'ctc', 'abc']
# b의 문자열 중 첫문자를 우선, 다음은 마지막 문자 기준 정렬
sorted(a, key=lambda s: (s[0], s[-1])) # ['abc', 'ctc', 'cde'] 

#람다대신 함수지정도 가능
def fn(s):
  return s[0], s[-1]

print(sorted(a, key=fn))

#딕셔너리 key로 정렬
d1 = sorted(d.items())

#딕셔너리 val로 정렬
d2 = sorted(d.items(), key=lambda x: x[1])

 

반응형

파이썬 딕셔너리 사용 시 유용한 컨테이너 자료형들의 용도와 사용법을 정리해보았다.

 

1. defaultdict

딕셔너리는 존재하지 않는 인덱스/키를 조회, 삭제 연산 시 각각 IndexError, KeyError가 발생한다.

그래서 다음처럼 에러가 발생하는 경우를 예외처리 하는 방법도 있다.

    a = {}  # 빈 딕셔너리
    
#1 try-except
    try:
        print(a['key'])  # 없는 키 조회 시
        del a['key']  # 없는 키 삭제 시
    except KeyError:
        print('KeyError 발생')

#2 if문
    if 'key' in a:
        print('Key 존재')
    else:
        print('존재하지 않는 Key')

 

defaultdict 객체는 존재하지 않는 키에 대한 연산을 할때 디폴트 값을 기준으로 딕셔너리 키:값을 생성해준다.

int, list 등 다양한 형태로 딕셔너리를 만들 수 있다.

list 딕셔너리는 키에 문자열도, 리스트도 삽입할 수 있다. 값을 넣어 줄 때는 리스트처럼 append를 사용하면 된다.

 

    a = collections.defaultdict(int) 
    a['key'] += 10
    print(a) #defaultdict(<class 'int'>, {'key': 10})
    
    b = collections.defaultdict(list) 
    b[0].append([1,2,3])
    b[0].append('to')
    print(b) #defaultdict(<class 'list'>, {0: [[1, 2, 3], 'to']})

 

 

 

2. Counter

Counter는 아이템에 대한 개수를 계산해 딕셔너리로 리턴한다. (개사기)

most_common(n) 로 Counter 객체의 n번째까지 빈도가 높은 요소를 출력할 수도 있다.  

    a = [2,4,1,1,1,1,5,5,5,3,6]
    b = collections.Counter(a)
    print(b) #Counter({1: 4, 5: 3, 2: 1, 4: 1, 3: 1, 6: 1})
    print(b.most_common(2)) #[(1, 4), (5, 3)]

 

+ 딕셔너리는 해시테이블을 이용한 자료형으로 입력 순서가 유지되지 않아 입력순서를 유지하려면 OrderedDict 이라는 객체를 사용해야했으나 파이썬 3.7부터는 딕셔너리도 내부적으로 인덱스를 이용해 입력 순서가 유지되도록 개선됐다.

 


Reference

책) 파이썬 알고리즘 인터뷰 (박상길) 

반응형

해시 문제를 풀다가 딕셔너리에 값을 추가하는 법에 대해 찾아보았다.

 

collections 라이브러리의 defaultdict 이라는 함수를 사용해서 값 추가가 가능하다. 

 

from collections import defaultdict
clothes=[["yellowhat", "headgear"], ["bluesunglasses", "eyewear"], ["green_turban", "headgear"]]
size=len(clothes)
dic=defaultdict(list)

for i in range(size):
    dic[clothes[i][1]].append(clothes[i][0])

print(dic)
print(dic.values())
print(dic.keys())
print()
dic['headgear'].remove('yellowhat')
print(dic)

 

 

실행 결과

 

위 실행결과를 보면 리스트 처럼 딕셔너리에 append(), remove() 함수를 사용할 수 있다.

반응형

소프트웨어 공학 관점에서 S/W의 질을 향상하는 법

>>> 강한 응집력(Strong Cohesion), 약한 결합력(Weak Coupling) 지향

OOP = 클래스를 사용하여 강한 응집력, 클래스간에 독립적인 설계로 약한 결합력을 지향

 


 

객체 지향 프로그래밍의 특징

 

1. 캡슐화

 

객체의 속성(데이터 필드)과 행위(메소드)를 하나로 결합

실제 구현 내용 일부를 외부에 은닉 (접근 제어자 public/ protected/ private 로 정보은닉)

접근지정자에 의해 제한된 멤버들은 컴파일러에 의해 판단됨

> 제한된 멤버 접근 시 컴파일 오류, 실행코드 생성 제한

 

 

 

2. 추상화

 

객체들의 공통된 특징 파악, 정의

> 불필요한 정보는 숨기고 중요한 정보만 표현. 프로그램을 간단히 만드는 것

  • 클래스 = 추상 자료형
  • 객체 = 추상 자료형의 인스턴스
  • 메소드 = 추상 자료형에서 정의된 연산
  • 생서자 = 메소드 호출 
  • 추상클래스 (abstract) : 추상메소드 포함 (미완성 클래스) > 객체 생성 불가능 (Is-a)
  • 인터페이스 (interace)  : 추상메소드, 상수 포함 > 다중상속 (implements) (has-a)

 

 

 

3. 다형성 (오버라이딩/오버로딩)

 

같은 형태에 다른 기능 > 코드의 재사용성 증가, 유지보수 용이

  • 오버라이딩
    • 부모 클래스를 상속받아 자식 클래스에서 부모클래스의 메소드를 재정의

 

  • 오버로딩
    • 같은 이름의 메소드매개변수의 갯수데이터 타입을 다르게 정의

 



4. 상속성 (재사용)


새로운 클래스가 기존의 클래스의 자료와 연산을 이용할 수 있게 하는 기능 > 코드의 중복 최소화

클래스 간의 종속 관계를 형성 > 객체 조직화



동적 바인딩
실행 시간 중에 일어나거나 실행 과정에서 변경될 수 있는 바인딩

프로그램의 한 개체나 기호를 실행 과정에 여러 속성이나 연산에 바인딩함으로써 다형 개념을 실현

 

정적 바인딩

컴파일 시간에 완료되어 변화하지 않음

 


Reference

 

객체 지향 프로그래밍 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 객체 지향 프로그래밍(영어: Object-Oriented Programming, OOP)은 컴퓨터 프로그래밍의 패러다임 중 하나이다. 객체 지향 프로그래밍은 컴퓨터 프로그램을 명령어의 목

ko.wikipedia.org

 

 

OOP(Object-Oriented Programming, 객체 지향 프로그래밍) 이란?

OOP란 무엇인가? OOP (Object-Oriented Programming)이란 객체 지향적인 프로그래밍. 즉, C언어같은 절차 지향적인 프로그래밍이 아닌 객체의 관점에서 프로그래밍을 한다는 것이다. OOP는 객체를 기준으로

velog.io

 

반응형

'Program Language > Java' 카테고리의 다른 글

🧐 JVM, JRE, JDK, GC, JAVA 실행과정, etc...  (0) 2022.07.24

+ Recent posts