자료구조/알고리즘 - 중복 순열/순열/조합, DP의 알고리즘 예시

2021. 11. 15. 15:29·SE Bootcamp 내용 정리

중복 순열/순열/조합

조합: 순서 상관x
순열: 순서 상관 o
중복순열: 순서도 상관x, 중복도 상관x

 

먼저 반복문(for문)만으로 만들어서 생각해보자

for문을 이용한 순열/조합

중복 순열

중복 순열: 3개 중 3개를 뽑아서 중복 순열을 만든다면?
→ for 반복문을 3중으로 쓰면 된다 (3중 for문)

// 3개 중 3개를 뽑는 중복순열의 예

let result=[];
const game = ['rock', 'paper', 'scissors'];

for(let i=0;i < game.length; i++){
    for(let j=0;j < game.length; j++){
        for(let k=0; k< game.length; k++){
            result.push([game[i], game[j], game[k]]);
        }
    }
}
return result;

단, 이는 시간복잡도를 고려치 못한 구문으로, 시간 복잡도 면에서 비효율적
→ O(N^3); O(N^2)의 복잡도 형태를 가짐

순열

3개 중에서 3개를 뽑아서 순열을 만들자 for 반복문
→ 중복 순열에서 중복되는 경우를 제외시키면 된다

// 3개 중 3개를 뽑는 중복순열의 예

let result=[];
const game = ['rock', 'paper', 'scissors'];

for(let i=0;i < game.length; i++){
    for(let j=0;j < game.length; j++){
        for(let k=0; k< game.length; k++){
            // 중복되는 경우에는 그냥 넘어가자(제외)
            if(i===j || j===k || k===i) continue;
            result.push([game[i], game[j], game[k]]);
        }
    }
}
return result;

조합

3개 중 2개를 뽑아서 조합을 만들자 for 반복문

let result=[];
const game = ['rock', 'paper', 'scissors'];

for(let i=0;i < game.length; i++){
    for(let j=i+1;j < game.length; j++){    //    j는 항상 i보다 1 크다
        // 앞에 하나를 빼서 나열한 상태에서 나머지를 붙인다는 개념이므로!
        result.push([game[i], game[j]]);    
    }
}
return result;
  • 여기서 의문점? 그런데 7개중 6개를 뽑아서 만든다면, 6중 포문?
    11개 중 10개는 10중 포문?

→ 로직 짜는 거 자체가 노답이다...(시간 복잡도 또한 노답)

 

반복문으로 할 수 있다면?
→ 재귀로도 할 수 있다는 것을 떠올려야 한다

재귀 함수를 이용한 순열/조합

중복 순열

3개중 3개를 뽑아서 중복 순열을 만들자 with 재귀

// 3개 중 3개를 뽑는 중복순열의 예 (재귀)

let result=[];    // 결과를 담을 배열
const game = ['rock', 'paper', 'scissors'];

const recursion= function(cnt, bucket){
    if(cnt===0){    // 탈출 조건    //출입국 심사 관리소 역할    //cnt는 1씩 감소하도록 설계
    result.push(bucket);
    return;    //해당 함수가 종료됨
    }

for(let i=0;i < game.length; i++){
    const pick=game[i];
    recursion(cnt-1, bucket.concat(pick));
    // 1개 넣은 상태(pick)에서 나머지들을 채우는 거니깐(재귀)
// 리턴으로 해당 함수가 종료되었어도 아직 반복문은 다 돌지 않았으니깐 다시 반복문의
// 인덱스가 올라가면서 다시 진입한다는 것!(바로 윗 단계로 올라간다 생각하면 된다)

}
}

recursion(3, []);    //3개를 뽑으므로 3, 초기 배열은 []로 시작

순열, 조합도 결국 이 구조를 응용한 거라서 나머지(rest)부분만 바뀌는 구조(나머지에 대한 코드 로직만 작성하고 수정하면 됨)

 

DP(동적 프로그래밍)

작은 문제를 풀어서 그 답을 구한다. 그 답을 좀 더 큰 문제를 구하는데 사용한다.(여러 번 반복해서 사용)

 

구해 둔 작은 문제의 답을 메모해두고, 그 것을 참조하면서 푸는 것
→ 구해 둔 작은 문제를 또 다시 풀지 않는다는 게 중요!

 

아래의 배낭(knapsack) 문제 알고리즘이 대표적인 예

// 화폐 종류 (type)을 가지고 특정 금액(target)을 만드는 알고리즘의 예

// target 10 이면
// 지폐 종류가 1 2 5 가 있다고 가정 // type=[1,2,5]
// 1 2 5를 가지고 10을 만드는 경우의 수

//bag이라는 경우의 수를 저장하는 배열을 생성
// 이 배열의 길이는 target+1의 크기만큼 되도록 더미 배열 생성
// 인덱스는 항상 0부터 시작하므로 내가 원하는 값의 경우의 수를 직관적으로 보기 위해...

//bag[0]=1 을 한 이유는 0원을 만드는 방법은 아무것도 안넣는 방법 1가지 이므로
//동전종류(type) / target(구하고자하는 금액)
 // 1 2 3 4 5 6 7 8 9 10 <- 만들어야 하는 액수(인덱스로 쳐서 생각)
//1 1 1 1 1 1 1 1 1 1 1 <-만들수있는 방법 가짓수
//2 0 1 1 2 2 3 3 4 4 5 // 3을 구할때, 3에서 2는 반드시 들어가야 한다. 그렇다면, 3-2=1 , 1을 구하는 모든 경우의 수(total)를 구하는 것과 같다
//5 0 0 0 0 1 1 2 2 3 4
//t2 1 2 2 3 3 4 4 5 5 6 // 2까지 탐색시의 total

//t5 1 2 2 3 4 5 6 7 8 10 // 5까지 탐색시의 total

//    이를 이용한 코드

let bag = new Array(target+1).fill(0) // 타겟의 크기+1 만큼 공간을 가지는 변수 // 배열의 길이는 target 숫자보다 1만큼 더 크다
//bag에 경우의 수의 합을 넣는다
bag[0]=1; //초기값으로 1을 가지고 시작 [1, 0,0,0,0,..., 0] // 0 1 2 3 4 5로 생각!
// let result=0;
for(let i=0;i < type.length;i++){ 
    for(let j=1;j <= target;j++){//target의 길이만큼 반복 대신 1부터 시작
        if(type[i] <= j){ // 지폐 숫자보다 크다면 
            bag[j]=bag[j]+bag[j-type[i]]; // 기존 경우의 수에 type[i]를 뺀 금액을 만들 수 있는 경우의 수를 더해준다
        }
    }
}

return bag[target];
저작자표시 (새창열림)

'SE Bootcamp 내용 정리' 카테고리의 다른 글

데이터베이스 - MVC 패턴 기초  (0) 2021.11.16
데이터베이스 - 관계형 데이터베이스 보충 내용  (0) 2021.11.15
자료구조/알고리즘 - 정규표현식  (0) 2021.11.11
자료구조/알고리즘 - 코딩 테스트 2  (0) 2021.11.11
자료구조/알고리즘 - 코딩 테스트 1  (0) 2021.11.11
'SE Bootcamp 내용 정리' 카테고리의 다른 글
  • 데이터베이스 - MVC 패턴 기초
  • 데이터베이스 - 관계형 데이터베이스 보충 내용
  • 자료구조/알고리즘 - 정규표현식
  • 자료구조/알고리즘 - 코딩 테스트 2
레실이
레실이
  • 레실이
    레실이의 티스토리
    레실이
  • 전체
    오늘
    어제
    • 분류 전체보기 (91)
      • SE Bootcamp 내용 정리 (63)
      • 알고리즘 연습 (7)
      • Project 주저리 (4)
      • 기술 면접 source (3)
      • 개발 일상 (12)
      • 생성 AI 활용 (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    JS
    CSR
    데이터베이스
    CSS
    인증/보안
    react
    useState
    알고리즘
    CORS
    Ajax
    promise
    JavaScript
    mongoDB
    Linux
    MVC
    Python
    ORM
    state
    node.js
    PickAndDrink
    node
    DOM
    IT
    문자열
    객체
    비동기
    ubuntu
    useRef
    fastapi
    자료구조
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
레실이
자료구조/알고리즘 - 중복 순열/순열/조합, DP의 알고리즘 예시
상단으로

티스토리툴바