λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
5️⃣ CS/Algorithm

[Java Algorithm Note] μˆœμ—΄ (feat. μž¬κ·€)

by seolhee2750 2022. 8. 15.

μˆœμ—΄, μ‘°ν•©, 뢀뢄집합 이 세가지에 λŒ€ν•΄μ„œ μ€‘μš”ν•˜κ²Œ 생각을 λͺ»ν–ˆλŠ”데,

μ΄λ²ˆμ— λ°°μ›Œλ³΄λ‹ˆ 정말 λ„ˆλ¬΄λ„ˆλ¬΄ μ€‘μš”ν•œ 것듀이어따..!!

이것듀을 κ³΅λΆ€ν•˜κ³ λ‚˜λ‹ˆ λ¬Έμ œμ—μ„œλ„ λ‹€μ–‘ν•˜κ²Œ ν™œμš©ν•  수 있음

κ·Έλž˜μ„œ μ˜€λŠ˜μ€ κ·Έ 쀑 첫 번째둜 μˆœμ—΄μ„ κ΅¬ν˜„ν•˜λŠ” 방법에 λŒ€ν•΄ μ •λ¦¬ν•΄λ³΄λ €ν•œλ‹€.

 

πŸ“Ž μˆœμ—΄

μˆœμ—΄μ€ μ„œλ‘œ λ‹€λ₯Έ n개의 μ›μ†Œμ—μ„œ r개λ₯Ό μˆœμ„œμ— μƒκ΄€μžˆκ²Œ 선택 ν˜Ήμ€ λ‚˜μ—΄ν•˜λŠ” 것을 λ§ν•œλ‹€.

 

예λ₯Ό λ“€μ–΄ {1, 2, 3}의 배열이 μžˆλ‹€κ³  ν•˜λ©΄,

{1, 2, 3}, {1, 3, 2}, {2, 1, 3}, {2, 3, 1}, {3, 1, 2}, ... 이런 μ‹μœΌλ‘œ λ‚˜μ—΄λ˜λŠ” 것!

 

μ—¬κΈ°μ„œ μ€‘μš”ν•œ 점은 {1, 2, 3}κ³Ό {3, 2, 1}이 μ„œλ‘œ λ‹€λ₯΄λ‹€λŠ” 것이닀.

κΈ°λ³Έ μˆœμ—΄μ€ 쀑볡은 ν—ˆμš©ν•˜μ§€ μ•Šμ§€λ§Œ μˆœμ„œλ₯Ό 가지기 λ•Œλ¬Έμ— μˆœμ„œκ°€ λ‹€λ₯΄λ©΄ λ‹€λ₯Έ μˆœμ—΄λ‘œ λ³Έλ‹€.

 

쀑볡이 μ‘΄μž¬ν•˜λŠ” μˆ˜μ—΄λ„ μžˆλŠ”λ°, μ΄λŠ” 쀑볡 μˆ˜μ—΄μ΄λΌκ³  ν•œλ‹€.

쀑볡 μˆœμ—΄μ€ {1, 1, 1}, {1, 1, 2}, {1, 1, 3}, {1, 2, 1}, ... κ³Ό 같이 쀑볡을 ν—ˆμš©ν•œλ‹€.

 

πŸ‘‰ μ •λ¦¬ν•˜μžλ©΄,

κΈ°λ³Έ μˆœμ—΄μ€ 쀑볡은 ν—ˆμš©ν•˜μ§€ μ•Šκ³  μˆœμ„œλ§Œ 있고,

쀑볡 μˆœμ—΄μ€ 쀑볡과 μˆœμ„œκ°€ λͺ¨λ‘ μžˆλŠ” μˆœμ—΄!!


πŸ“Ž κΈ°λ³Έ μˆœμ—΄ κ΅¬ν˜„

public class Permutation1 {
	
	static char[] src = { 'a', 'b', 'c', 'd' };

	/*
     * κΈ°λ³Έ μˆœμ—΄ - 쀑볡 X, μˆœμ„œ O
     * @param nth - λͺ‡ 번째 선택인지 ν‘œν˜„
     * @param choosed - μ„ νƒλœ μš”μ†Œ
     * @param visited - μ‚¬μš©λœ 적 μžˆλŠ” μš”μ†Œλ“€ 기둝
     */
	static void makePermutation(int nth, char[] choosed, boolean[] visited) {
    	if(nth == choosed.length) { // κΈ°μ € 쑰건: choosedλ₯Ό λ‹€ 채웠닀면 끝
    		System.out.println(Arrays.toString(choosed));
    		return;
    	}
    	
    	for(int i = 0; i < src.length; i++) {
    		if(!visited[i]) {
    			visited[i] = true; // ν•΄λ‹Ή μš”μ†Œ μ„ νƒλ˜μ—ˆμŒμ„ 기둝 (쀑볡 방지λ₯Ό μœ„ν•¨)
    			choosed[nth] = src[i]; // ν•΄λ‹Ή μš”μ†Œ μ„ νƒν•˜κΈ°
    			makePermutation(nth+1, choosed, visited); // λͺ‡ 번째 선택인지 카운트, μ„ νƒλœ μš”μ†Œ true둜 바뀐 visited ν•¨κ»˜ λ„˜κ²¨μ£ΌκΈ°
    			visited[i] = false; // ν•΄λ‹Ή μš”μ†Œλ₯Ό λ‹€μ‹œ false둜 λ°”κΏ”μ£Όμ–΄ λ‹€μŒ μˆœμ—΄μ—μ„œλŠ” μ‚¬μš©ν•  수 있게 ν•΄μ£ΌκΈ°
    		}
    	}
    }
	
	public static void main(String[] args) {
        System.out.println("μˆœμ—΄");
        makePermutation(0, new char[3], new boolean[src.length]); // srcμ—μ„œ 3개λ₯Ό 뽑아 λ§Œλ“€ 수 μžˆλŠ” μˆœμ—΄μ„ λͺ¨λ‘ 좜λ ₯
	}

}

nth νŒŒλΌλ―Έν„°λ₯Ό μ΄μš©ν•˜μ—¬ ν˜„μž¬μ˜ μš”μ†Œ 선택이 λͺ‡ λ²ˆμ§ΈμΈμ§€λ₯Ό ν‘œν˜„ν•˜κ³ ,

choosedμ—λŠ” ν˜„μž¬ μ„ νƒν•œ μš”μ†Œλ₯Ό λ‹΄μ•„μ„œ μˆœμ—΄μ„ μ™„μ„±μ‹œν‚¬ 수 있게 ν–ˆλ‹€.

visitedλŠ” 쀑볡을 ν”Όν•˜κΈ° μœ„ν•΄ μ‚¬μš©ν–ˆλ‹€.


πŸ“Ž 쀑볡 μˆœμ—΄ κ΅¬ν˜„

public class Permutation2 {
	
	static char[] src = { 'a', 'b', 'c', 'd' };
	
	/*
     * 쀑볡 μˆœμ—΄ - 쀑볡 O, μˆœμ„œ O
     * ex) abc aab --> 쀑볡 μˆœμ—΄
     * κΈ°λ³Έ μˆœμ—΄μ—μ„œ visited만 λΉΌμ£Όλ©΄ ok
     * 
     * @param nth - λͺ‡ 번째 선택인지 ν‘œν˜„
     * @param choosed - μ„ νƒλœ μš”μ†Œ
     */
	static void makePermutationDup(int nth, char[] choosed) {
    	if(nth == choosed.length) { // κΈ°μ € 쑰건: choosedλ₯Ό λ‹€ 채웠닀면 끝
    		System.out.println(Arrays.toString(choosed));
    		return;
    	}
    	
    	for(int i = 0; i < src.length; i++) {
    		choosed[nth] = src[i]; // ν•΄λ‹Ή μš”μ†Œ μ„ νƒν•˜κΈ°
			makePermutationDup(nth+1, choosed); // visited 기둝 ν•„μš” 없이, λͺ‡ 번째 μ„ νƒμΈμ§€λ§Œ 카운트 ν•΄μ£Όλ©΄ ok
    	}
    }
	
	public static void main(String[] args) {
        System.out.println("μˆœμ—΄");
        makePermutationDup(0, new char[3]); // srcμ—μ„œ 3개λ₯Ό 뽑아 λ§Œλ“€ 수 μžˆλŠ” 쀑볡 μˆœμ—΄μ„ λͺ¨λ‘ 좜λ ₯
	}

}

쀑볡 μˆœμ—΄μ€ κΈ°λ³Έ μˆœμ—΄κ³Ό 거의 λ™μΌν•œλ°,

쀑볡을 ν—ˆμš©ν•˜λ―€λ‘œ visited λ°°μ—΄λ§Œ λΉΌμ£Όμ—ˆλ‹€.


πŸ‘€ 정리

μˆœμ—΄μ€ 쀑볡 없이 μš”μ†Œλ“€μ„ 뽑아 λ‚˜μ—΄ν•œ 것을 μ˜λ―Έν•˜κ³ ,

쀑볡 μˆœμ—΄μ€ 쀑볡을 ν—ˆμš©ν•˜μ—¬ μš”μ†Œλ“€μ„ 뽑아 λ‚˜μ—΄ν•œ 것을 말함

μˆœμ—΄κ³Ό 쀑볡 μˆœμ—΄μ€ λͺ¨λ‘ μž¬κ·€ λ°©μ‹μœΌλ‘œ κ°„λ‹¨νžˆ κ΅¬ν˜„ν•  수 μžˆλŠ”λ°,

μˆœμ—΄ κ΅¬ν˜„ λ©”μ„œλ“œμ—μ„œ visited λ°°μ—΄λ§Œ μ œκ±°ν•΄μ£Όλ©΄ 쀑볡 μˆœμ—΄μ΄ λœλ‹€.

λŒ“κΈ€