[프로그래머스 - JAVA] 숫자 카드 나누기

2024. 7. 17. 10:52Algorithm

 

문제 설명

 

철수와 영희는 선생님으로부터 숫자가 하나씩 적힌 카드들을 절반씩 나눠서 가진 후, 다음 두 조건 중 하나를 만족하는 가장 큰 양의 정수 a의 값을 구하려고 합니다.

  1. 철수가 가진 카드들에 적힌 모든 숫자를 나눌 수 있고 영희가 가진 카드들에 적힌 모든 숫자들 중 하나도 나눌 수 없는 양의 정수 a
  2. 영희가 가진 카드들에 적힌 모든 숫자를 나눌 수 있고, 철수가 가진 카드들에 적힌 모든 숫자들 중 하나도 나눌 수 없는 양의 정수 a

예를 들어, 카드들에 10, 5, 20, 17이 적혀 있는 경우에 대해 생각해 봅시다. 만약, 철수가 [10, 17]이 적힌 카드를 갖고, 영희가 [5, 20]이 적힌 카드를 갖는다면 두 조건 중 하나를 만족하는 양의 정수 a는 존재하지 않습니다. 하지만, 철수가 [10, 20]이 적힌 카드를 갖고, 영희가 [5, 17]이 적힌 카드를 갖는다면, 철수가 가진 카드들의 숫자는 모두 10으로 나눌 수 있고, 영희가 가진 카드들의 숫자는 모두 10으로 나눌 수 없습니다. 따라서 철수와 영희는 각각 [10, 20]이 적힌 카드, [5, 17]이 적힌 카드로 나눠 가졌다면 조건에 해당하는 양의 정수 a는 10이 됩니다.

철수가 가진 카드에 적힌 숫자들을 나타내는 정수 배열 arrayA와 영희가 가진 카드에 적힌 숫자들을 나타내는 정수 배열 arrayB가 주어졌을 때, 주어진 조건을 만족하는 가장 큰 양의 정수 a를 return하도록 solution 함수를 완성해 주세요. 만약, 조건을 만족하는 a가 없다면, 0을 return 해 주세요.

 

제한사항
  • 1 ≤ arrayA의 길이 = arrayB의 길이 ≤ 500,000
  • 1 ≤ arrayA의 원소, arrayB의 원소 ≤ 100,000,000
  • arrayA arrayB에는 중복된 원소가 있을 있습니다.

 

입출력 예
arrayA arrayB result
[10, 17] [5, 20] 0
[10, 20] [5, 17] 10
[14, 35, 119] [18, 30, 102] 7

 

풀이

 

간단하게 말하면 둘 중 하나의 배열을 선택하고 해당 값에서 선택한 값으로 모두 나누어 떨어지고 다른 배열에서는 하나도 나누어 떨어지는 값이 없는 경우의 최대값을 구하면 된다.

 

일단 첫번째로 해야되는 건 나누어 떨어지는 값의 최대를 구해야한다. 기본적으로 각각의 배열의 최소 값 즉 첫번 째 값을 선택해야 모두 나누어 떨어지는 경우를 찾을 수 있다. 그리고 해당 값을 이용해 약수를 구하고 10 -> 1, 2, 5, 10 이렇게 이 중 나누어 떨어지는 값이 제일 큰 경우를 선택하면 된다. 그런데 1은 항상 만족하므로 제외하고 계산해야된다. 

 

풀이-1

 

import java.util.*;

class Solution {
    
    HashSet<Integer> result = new HashSet<>();
    
    public int solution(int[] arrayA, int[] arrayB) {
        
        // 약수 구하기
        ArrayList<Integer> arrA = div(arrayA[0]);
        ArrayList<Integer> arrB = div(arrayB[0]);
        
        int[] listA = arrA.stream().mapToInt(i -> i).toArray();
        int[] listB = arrB.stream().mapToInt(i -> i).toArray();
        
        // 최대 값 구하기
        maximum(listA, arrayA, arrayB);
        maximum(listB, arrayB, arrayA);
        
        if (result.isEmpty()) return 0;
        return Collections.max(result);
    }
    
    public void maximum(int[] list, int[] mainArr, int[] subArr) {
        
        for (int arr : list) {
            boolean v = false;
            for (int i = 0; i < mainArr.length; i++) {
                // 배일 값 만큼 반복
                if (mainArr[i] % arr == 0 && subArr[i] % arr != 0) {
                    continue;
                }
                v = true;
                break;
            }
            if (!v) {
                result.add(arr);
            }
        }
        
    }
    
    public ArrayList<Integer> div(int num) {
        ArrayList<Integer> arr = new ArrayList<>();
        
        for (int i = 1; i <= Math.sqrt(num); i++) {
            if (num % i == 0) {
                if (i != 1) {
                    // i가 1이 아닌 나눠 떨어지는 경우
                    arr.add(i);
                }
                // 나눠 떨어지는 몫도 포함
                arr.add(num / i);
            }
        }
        
        return arr;
    }
    
}

 

풀이-2

 

import java.util.*;

class Solution {
    
    HashSet<Integer> result = new HashSet<>();
    
    public int solution(int[] arrayA, int[] arrayB) {
        
        // 약수 구하기
        ArrayList<Integer> arrA = div(arrayA[0]);
        ArrayList<Integer> arrB = div(arrayB[0]);
        
        // 최대 값 구하기
        maximum(arrA, arrayA, arrayB);
        maximum(arrB, arrayB, arrayA);
        
        if (result.isEmpty()) return 0;
        return Collections.max(result);
    }
    
    public void maximum(ArrayList<Integer> list, int[] mainArr, int[] subArr) {
        
        for (Integer arr : list) {
            boolean v = false;
            for (int i = 0; i < mainArr.length; i++) {
                // 배일 값 만큼 반복
                if (mainArr[i] % arr == 0 && subArr[i] % arr != 0) {
                    continue;
                }
                v = true;
                break;
            }
            if (!v) {
                result.add(arr);
            }
        }
        
    }
    
    public ArrayList<Integer> div(int num) {
        ArrayList<Integer> arr = new ArrayList<>();
        
        for (int i = 1; i <= Math.sqrt(num); i++) {
            if (num % i == 0) {
                if (i != 1) {
                    // i가 1이 아닌 나눠 떨어지는 경우
                    arr.add(i);
                }
                // 나눠 떨어지는 몫도 포함
                arr.add(num / i);
            }
        }
        
        return arr;
    }
    
}