2244. Minimum Rounds to Complete All Tasks

0번 부터 시작하는 인덱스가 주어지고 한번의 테스크는 2,3 개 만 이루어진다. 동일한 레벨 만 동시에 작업할수 있다.

최소 라운드 를 구해라 만약 없다면 -1 을 리턴 하라는 문제이다.

 

최대 갯수가 10000 개 밖에 되지않는다.

 

Map 을 이용해 저 숫자들 을 분류하고, bfs 를 이용해 최소 라운드 를 찾아갈 생각을 했다.

 

더보기
class Solution {
    public int minimumRounds(int[] tasks) {
        Map<Integer,Integer> map = new HashMap();
            for(int a:tasks){
                Integer b = map.getOrDefault(a,0);
                map.put(a,b+1);
            }

            int round = 0;
            for(Map.Entry<Integer,Integer> entry : map.entrySet()){
                Integer value = entry.getValue();
                if(value < 2) return -1;
                int calculate = calculate(value);
                if(calculate < 0) return -1;
                round += calculate;
            }

            return round;
    }

    private int calculate(Integer value) {
            int round =0;
            boolean found = false;

            Queue<Integer> q = new ArrayDeque<>();
            Set<Integer> set = new HashSet();
            q.add(0);

            while(!q.isEmpty()){
                int size = q.size();
                for(int i =0;i<size;i++){
                    int poll = q.poll();

                    int a = poll + 2;
                    if( a == value) return round+1;
                    int b = poll + 3;
                    if( b == value) return round+1;

                    if(a < value && set.add(a)) q.offer(a);
                    if(b < value && set.add(b)) q.offer(b);
                }
                round++;
            }

            return found ? round : -1;
        }
}

이렇게 작성했더니 무려 126ms 나 나와버렸더 무진장 느리다 ...  아무래도 저 bfs 부분이 문제인거 같은데 나름 최적화 가 되어있다고 생각하는데 이렇게 느린걸 보면 다른 규칙이 있는것 같다.

1번   2,3
2번  4,5,6
3번 7,8,9
4번 10,11,12

연산 을 한번 두번 .... 했을때 중복 값을 제외하고 나올 경우의 수를 작성해 보면 위와 같다. 파란색으로 마킹된 부분을 살펴보자. 

모두 3의 배수이다. 2,3 을 이용한다면 모든수 를 작성할수 있다 단 1 인 경우를 제외한다면 이다. caculate 함수 부분을 변경하자.

    private int calculate(Integer value) {
        if(value%3 == 0) return value/3;
        return (value/3)+1;
    }

좋다 이렇게 변경하니 속도가 개선 되었으나 여전히 36ms 로 상위 19% 이다. 많이 느리다. 어떤 부분을 놓친걸까...

 

더보기
class Solution {
    public int minimumRounds(int[] tasks) {
        Arrays.sort(tasks);
        int round = 0;
        int cnt = 1;
        if(tasks.length < 2) return -1;

        for(int i=1;i<tasks.length;i++){
            if(tasks[i-1] != tasks[i]){
                if(cnt < 2) return -1;
                round += calculate(cnt);
                cnt =1;
            }else{
                cnt++;
            }
        }
        
        if(cnt < 2) return -1;
        else round += calculate(cnt);

        return round;
    }

    private int calculate(Integer value) {
        if(value%3 == 0) return value/3;
        return (value/3)+1;
    }
}

 

로직을 변경해 배열을 정렬하고 for loop 으로 로직 변경 => 10ms  98.8% 까지 나왔다.

 

음 ? 다른사람의 풀이도 별반 다르지 않다... 다 이런 2가지 방식으로 풀었다.

 

83. Remove Duplicates from Sorted List

연결 노드상 에서 중복된 값을 지워주는 로직을 구현하면 된다. 재귀 를 노드 의 마지막 까지 이동을 하고

현재 헤드 기준으로 헤드 의 다음을 계속 업데이트 해주면서 날려주는 로직을 재귀 안에 구성하면 될것같다.

 

더보기
class Solution {
    public ListNode deleteDuplicates(ListNode head) {
        helper(head);
        return head;
    }
    public void helper(ListNode head){
        if(head == null || head.next == null) return;
        while(head.next != null && head.val == head.next.val){
            ListNode next = head.next;
            if(next == null){
                head.next = null;
                break;
            }
            head.next = next.next;
        }
        helper(head.next);
    }
}

null 체크 를 제대로 하지않아서 nullPointer exception 을 여러번 맞았다 ㅎㅎㅎ... while 을 next 의 null 까지 돌리지 않는다면 

1,1,1,1,1,1,1 케이스 에서 1,1 로 반환되는 불상사가 발생한다. 주의 하자

Solution 중에 가독성 좋은 코드가 있어서 가져와 봤다.

더보기
public class Solution {
    public ListNode deleteDuplicates(ListNode head) {
        ListNode list = head;
         
         while(list != null) {
        	 if (list.next == null) {
        		 break;
        	 }
        	 if (list.val == list.next.val) {
        		 list.next = list.next.next;
        	 } else {
        		 list = list.next;
        	 }
         }
         
         return head;
    }
}

while 을 이용해서 loop 를 돌리는게 확실히 재귀보다 직관적 이다.

 

1619. Mean of Array After Removing Some Elements

정렬하고 5% 계산해서 평균 구해주면 되는 Easy 난이도 에 맞는 문제이다.

더보기
class Solution {
    public double trimMean(int[] arr) {
        Arrays.sort(arr);
        int cut = (int) ((double) arr.length * 0.05);
        double sum = 0;
        for(int i = cut;i<arr.length-cut;i++){
            sum+=arr[i];
        }
        return sum/(arr.length-(cut*2));
    }
}

 

깔끔한 코드 20 개 의 배수가 주어진다는 문제의 요구사항에 따라 미리 20 을 나눠서 계산하는 모습이 인상적이다.

    public double trimMean(int[] arr) {
        int n = arr.length;
        double sum = 0d;
        Arrays.sort(arr);
        for (int i = n / 20; i < n - n / 20; ++i) {
            sum += arr[i];
        }
        return sum / (n * 9 / 10);
    }

 

'PS > LeetcCode' 카테고리의 다른 글

LeetCode Daily 문제풀기  (0) 2023.01.06
LeetCode Daily 문제풀기  (0) 2023.01.05
Easy 문제 풀기 Day2(83/618)  (0) 2023.01.03
Binary Tree Maximum Path Sum  (0) 2022.12.11
1339. Maximum Product of Splitted Binary Tree  (0) 2022.12.10

+ Recent posts