CS/자료구조

[자료구조] 기초수학 문제

meizzi 2024. 8. 16. 20:43
728x90
반응형

1. 파스칼 삼각형

  • 이항계수를 삼각형 모양의 기하학적인 형태로 배열한 것
  • 첫 번째 줄에는 숫자 1을 쓴다.
  • 그 다음 줄부터는 바로 위의 왼쪽 숫자와 오른쪽 숫자를 더한다.
  • 삼각형의 행의 수가 주어지면 파스칼의 삼각형 출력
  • 풀이
    • 행의 수에 대해 이중 반복문을 돌아 만일 j가 0이거나 i와 j가 같은 경우에는 외각 지역인 숫자가 1인 곳을 의미한다.
    • 아니면 위의 왼쪽 값과 오른쪽 값을 더하면 된다.
    • 왼쪽 값은 위의 배열인 i - 1에서 j - 1의 값 / 오른쪽 값은 위의 배열인 i - 1에서 j의 값 
public static ArrayList<ArrayList<Integer>> solution(int numRows) {
	ArrayList<ArrayList<Integer>> result = new ArrayList<>();
    
    for (int i = 0; i < numRows; i++) {
    	ArrayList<Integer> list = new ArrayList<>();
    	for (int j = 0; j < i + 1; j++) {
        	if(j == 0 || j == i) {
            	list.add(1);
            } else {
            	int x = result.get(i-1).get(j-1); // 왼쪽
                int y = result.get(i-1).get(j); // 오른쪽
                list.add(x+y);
            }
        }
        result.add(list);
    }
	return result;
}

2. 순열 응용

  • 양의 정수로 이루어진 arr 배열이 주어질 때 해당 데이터로 만들 수 있는 permutation 중 아래 조건 만족
    • 현재 데이터보다 이전의 큰 수 출력
    • 한 번의 swap으로 출력 가능한 큰 수 출력
  • 예시
    • 3, 2, 1 -> 3, 1, 2
    • 1, 9, 4, 7, 6 -> 1, 9, 4, 6, 7
    • 1, 1, 2, 3 -> 1, 1, 2, 3
  • 풀이
    • arr가 비어있거나 2보다 작은 경우에는 swap이 필요 없으니까 바로 반환
    • 인덱스 값을 -1로 저장해놓고 반복문을 거꾸로 돌면서 앞의 값이 현재 값보다 작으면 인덱스 값을 현재 i 값에서 1 감소
    • 만일 인덱스 값이 -1 그대로면 원래 arr 값 그대로 반환
    • 아니면 반복문을 한번 더 거꾸로 돌면서 만일 현재 값이 인덱스에 해당하는 값보다 작거나 만일 현재 값과 그 전 값이 같으면 그 값을 바꿀 경우 더 큰 수가 되기 때문에 다른 경우에만 값 변환
      • 현재 값과 인덱스에 해당하는 값 변경
public static void solution (int[] arr) {
	if (arr.lengrh == 0 || arr.length < 2) return;
    
    int idx = -1;
    for (int i = arr.length-1; i >= 1; i--) {
    	if (arr[i] < arr[i-1]) {
        	idx = i - 1;
            break;
        }
    }
    
    if (idx == -1) {
    	System.our.println(Arrays.toString(arr));
        return;
    }
    
    for (int i = arr.length-1; i > idx; i--) {
    	if (arr[i] < arr[idx] && arr[i] != arr[i-1]) {
        	int tmp = arr[i];
            arr[i] = arr[idx];
            arr[idx] = tmp;
            break;
        }
    }
}

3. 문자열 순열

  • 주어진 문자열 s1, s2에서 s1을 permutation을 한 문자열이 s2의 부분 문자열에 해당하면 true, 아니면 false 반환
  • 예시
    • s1: "ab" / s2: "adbak" -> true 반환
  •  풀이
    • 기본 permutation 활용
    • permutation을 한 문자열 배열을 구하고 contains로 문자열이 포함되어 있는지 확인
public static boolean solution (String s1, String s2) {
	boolean[] visited = new boolean[s1.length()];
    char[] out = new char[s1.length()];
    ArrayList<String> list = new ArrayList<>();
    permutation(s1.toCharArray(), 0, s1.length(), s1.length(), visited, out, list);
    
    for(String s : list) {
    	if(s2.contains(s)) return true;
    }
    
    return false;
}

 

4. 행복한 수 판별

  • 행복한 수
    • 각 자리수를 제곱한 것을 더하는 과정을 반복했을 때 1로 끝나는 수
  • 행복한 수가 아니라면 1에 도달하지 못하고 같은 수열 반복
  • 행복한 수라면 true, 아니면 false 반환
public static boolean solution (int n) {
	HashSet<Integer> set = new HashSet<>();
    
    while(set.add(n)) {
    	int sqaureSum = 0;
        
        while(n > 0) {
        	int remain = n % 10;
            sqaureSum += remain * remain;
            n /= 10;
        }
        
        if(sqaureSum == 1) {
        	return true;
        } else {
        	n = sqaureSum;
        }
    }
    return false;
}

5. 땅의 둘레

  • grid[i][j]가 1은 땅, 0은 물
  • grid한 cell의 변의 길이는 1
  • 지도에는 하나의 독립된 영토만 있고 분리된 땅은 없음
  • 땅 내부에 물은 존재하지 않음
  • 이때, 땅의 둘레 출력
  • 풀이
    • 방향 표시를 위한 이차원 배열 선언
    • 현재 땅이 1인 경우 방향 배열을 돌려 주변에 물이나 벽이 있는지 체크하여 맞으면 둘레 길이 1 증가
public static int solution (int[][] grid) {
	int[][] directions = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}};
	int cnt = 0;
    
    int row = grid.length;
    int col = grid[0].length;
    
    for (int i = 0; i < row; i++) {
    	for (int j = 0; j < col; j++) {
        	if(grid[i][j] == 1) {
            	for (int[] d : directions) {
                	int x = i + d[0];
                    int y = j + d[1];
                    
                    if(x < 0 || y < 0 || x >= row || y >= col || grid[x][y] == 0) {
                    	cnt++;
                    }
                }
            }
        }
    }
    return cnt;
}

6. 카탈랑 수

  • 카탈랑 수
    • 1, 1, 2, 5, 14, 42, 132, 429, ...
  • 카탈랑 수의 n번째 값
public static int solution (int n) {
	int result = 0;
    
    if (n <= 1) return 1;
    
    for(int i = 0; i < n; i++) {
    	result += solution(i) * solution(n-i-1);
    }
    return result;
}

7. 팰린드롬

  • 회문 또는 팰린드롬은 앞 뒤 방향으로 같은 순서의 문자로 구성된 문자열
    • ex) "abba", "kayak", "madam"
  • 유사회문은 문자열 그 자체는 회문이 아니지만 한 문자를 삭제하면 회문이 되는 문자열
  • 주어진 문자열을 확인 후 문자열 종류에 따라 다음과 같이 출력
    • 회문: 0 / 유사회문: 1 / 기타: 2
public static int solution (String str) {
	return isPalindrome(0, str.length-1, str.toCharArray(), 0);
}

public static int isPalindrome(int left, int right, char[] arr, int delCnt) {
	while(left < right) {
    	if(arr[left] != arr[right]) {
        	if(delCnt == 0) {
            	if(isPalindrome(left+1, right, arr, 1) == 0 || isPalindrome(left, right-1, arr, 1) == 0) {
                	return 1;
                } else {
                	return 2;
                }
            } else {
            	return 2;
            }
        } else {
            left++;
            right++;
        }
    }
    return 0;
}

8. 1차 방정식

  • 주어진 1차 방정식 풀이
  • 해당 방정식은 "+", "-", "x", 상수로만 구성
  • 해가 없으면 "No solution" 출력
  • 해가 무한대인 경우 "Infinite solutions" 출력
  • 해가 있는 경우 x의 값을 "x=" 형태로 출력
public static String solution (Stirng equation) {
	String[] parts = equation.split("=");
    int[] leftSide = evaluate(parts[0]);
    int[] rightSide = evaluate(parts[1]);
    
    if(leftSide[0] == rightSide[0] && leftSide[1] == rightSide[1]) {
    	return "Infinite solutions";
    } else if(leftSide[0] == rightSide[0]) {
    	return "No solution";
    } else {
    	return "x=" + (rightSide[1] - leftSide[1]) / (leftSide[0] - rightSide[0]);
    }
}

public static int[] evaluate (Stirng str) {
    int[] result = new int[2];
    
    boolean isMinus = false;
    int idx = 0;
    while (idx != str.length()) {
    	char c = str.charAt(idx++);
        
        if (c == "+") {
            continue;
        }
        
        if (c == "-") {
            isMinus = true;
            continue;
        }
        
        if (c == "x") {
            retult[0] += isMinus ? -1 : 1;
        } else {
            if (idx < str.length() && str.charAt(idx) == "x") {
                result[0] += isMinus ? -(c-'0') : (c-'0');
            } else {
            	result[1] += isMinus ? -(c-'0') : (c-'0');
            }
        }
        isMinus = false;
    }
    
    return result;
}

9. 좋은 수

  • 짝수 인덱스 위치에는 짝수
  • 홀수 인덱스 위치에는 소수 (2, 3, 5, 7)
  • 인덱스는 0부터 시작
  • 1 이상의 정수 n이 주어졌을 때, n 자리로 구성될 수 있는 좋은 수의 개수 출력
  • 단, n의 값에 따라 값이 클 수 있으니 결과는 10^9+7로 나머지 연산을 한 결과 출력
final static int mod = (int) 1e9 + 7;

public static int solution(long n) {
	return (int)(recursion(5, (n+1)/2) * recursion(4, n/2) % mod);
}

public static long recursion(long x, long y) {
	if(y == 0) return 1;
    
    long p = recursion(x, y/2);
    return p*p*(y%2>0 ? x:1);
}

10. 하노이의 탑

  • 한 번에 하나의 원판 이동 가능
  • 큰 원판이 작은 원판 위에 있으면 안됨
  • 원판의 개수가 n일 때, 가장 왼쪽 기중으로부터 끝 기둥으로 이동하는 과정에 대해 출력
static StringBuffer sb;

public static void solution(int n) {
    sb = new StringBuffer();
    hanoi(n, 1, 2, 3);
    System.out.println(sb);
}

public static void hanoi(int n, int start, int mid, int to) {
    if(n == 1) {
        sb.append(start + " " + to + "\n");
        return;
    }
    
    hanoi(n-1, start, to, mid);
    sb.append(start + " " + to + "\n");
    hanoi(n-1, mid, start, to);
}
728x90
반응형