LeetCode 문제 중 난이도 EasyOccurrences After Bigram이다. 문제 링크는 포스팅의 맨 마지막에 추가하였다. 언어는 Java를 사용했다.



  문제해석


주어진 first와 second를 이용해 "first second third" 형태의 텍스트로 first바로 다음에 second가 오고 바로 뒤에 third가 오는 경우를 고려하여라.

각각의 경우에 third를 answer에 추가하고 answer를 리턴하라.






1 처음엔 text 내third가 몇개인지 알 수 없으므로 크기가 고정된 배열 대신 리스트를 이용하자.

2 text에 있는 단어들을 문자열 배열 words에 넣어준다.

3 words[i]가 first이고 words[i+1]이면 words[i+2]를 answer에 추가한다.

4 마지막으로 answer를 배열로 변환하여 리턴한다.


코드로 나타내면 다음과 같다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Solution {
    public String[] findOcurrences(String text, String first, String second) {
        
        List<String> answer = new ArrayList<>();
        
        String[] words = text.split(" ");
        for(int i=0 ; i<words.length-2 ; i++){
            if(words[i].equals(first) && words[i+1].equals(second)){
                answer.add(words[i+2]);
            }
        }
        return answer.toArray(new String[0]);
    }
}
cs


위 코드의 시간복잡도는 O(n), 공간복잡도는 O(n)이다.


문제출처 - https://leetcode.com/problems/occurrences-after-bigram/



LeetCode 문제 중 난이도 EasyFlipping an Image이다. 문제 링크는 포스팅의 맨 마지막에 추가하였다. 언어는 Java를 사용했다.



  문제해석

2진 행렬 A를 입력으로 받아 수평으로 뒤집은 다음 숫자를 반대로 바꾸고 결과를 반환하라. 

수평으로 뒤집는것은 각 줄의 이미지가 뒤집히는 것이다. 예를들어 [1,1,0]을 수평으로 뒤집으면 [0,1,1]이 된다.

반대로 바꾸는것은 0은 1로, 1은 0으로 변환하는것이다. 예를들어 [0,1,1]은 [1,0,0]이 된다.







설명이 복잡해 보일때에는 Example을 보자. 우리가 해야 할 일은 입력 배열을 좌우로 뒤집은 뒤 0은 1로, 1은 0으로 바꿔서 반환해주기만 하면 된다.


위의 예시의 첫번째 행을 보자. A[0][2]을 temp에 넣고 A[0][2]에는 A[0][0]의 값과 1의 XOR 연산값(0을 1로, 1을 0으로)을 넣어주자. 위의 예시에서는 가운데 열인 A[0][1]은 temp에 넣을 필요 없이 A[0][1]^1만 해주면 되지만 열이 짝수인 경우에는 temp에 넣고 값을 서로 바꾸어주어야 한다. 반복문으로 전체 행에 연산해준다. XOR연산을 잘 모른다면 아래 비트연산자 포스팅을 참고한다.

2019/03/16 - [프로그래밍문제풀기] - 비트연산자란?




1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution {
    public int[][] flipAndInvertImage(int[][] A) {
        
        for(int i=0 ; i<A.length; i++){
            for(int j=0 ; j<(A[0].length+1)/2 ; j++){
                int temp = A[i][A[0].length-j-1];
                A[i][A[0].length-j-1= A[i][j]^1;
                A[i][j] = temp^1;
            }
        }
        return A;
    }
}
cs


이 방법의 시간복잡도는 O(n)이고 공간복잡도는 O(1)이다.


문제 출처 - https://leetcode.com/problems/flipping-an-image/





LeetCode 문제 중 난이도 EasyLemonade Change이다. 문제 링크는 포스팅의 맨 마지막에 추가하였다. 언어는 Java를 사용했다.



  문제해석


레몬에이드 가판대에서 각 레몬에이드의 가격은 $5이다.

레몬에이드를 사기 위해 줄에 선 손님들은 순서대로 한명씩 주문한다. 각각의 손님들은 $5, $10, $20 셋 중에 하나의 지폐를 내고 레몬에이드를 하나씩 주문한다. 정확하게 거스름돈을 돌려주어서 순수한 거래는 손님이 $5씩 지불한게 되어야 한다.

처음에 잔돈 없이 시작해서 모든 손님들에게 정확한 거스름돈을 돌려줄 수 있는 경우에만 true를 리턴하라.







가지고 있는 지폐 수를 체크하기 위해서 5달러 지폐의 수는 five, 10달러 지폐의 수는 ten이라는 변수에 넣는다. 20달러는 거스름돈으로 나갈 일이 없으므로 체크할 필요 없다. 5달러 지폐를 받으면 five+1, 10달러지폐를 받으면 ten+1을 해준다.


20달러 지폐를 받은 경우에는 두가지로 나눌 수 있다. 거스름돈을 10+5 합쳐서 줄 수도 있고 만약에 10달러가 없으면 5+5+5로 줄 수도 있다. 가지고 있는 5달러와 10달러 지폐가 음수가 되는 때가 있다면 거스름돈을 정확하게 돌려줄 수 없는 것이다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Solution {
    public boolean lemonadeChange(int[] bills) {
        int five=0, ten=0;
        
        for(int b : bills) {
            if(b==5){
                five++;
            }else if(b==10) {
                ten++;
                five--;
            }else if(b==20 && ten==0) {
                five-=3;
            }else{
                ten--;
                five--;
            }
            
            if(five<0 || ten<0return false;
        }
        
        return true;
    }
}
cs


한가지 유의할 점은 if(five<0 || ten<0) return false는 for문 안에 있어야 한다. 그렇지 않으면 지폐수가 음수였다가 다음 손님들에게 지폐를 받는, 실제로 존재할 수 없는 경우에도 true를 리턴한다.


이 코드의 시간복잡도는 O(n), 공간복잡도는 O(1)이다.



문제 출처 - https://leetcode.com/problems/lemonade-change/






LeetCode 문제 중 난이도 EasyStudent Attendance Record I이다. 문제 링크는 포스팅의 맨 마지막에 추가하였다. 언어는 Java를 사용했다



  문제해석


학생의 출석기록을 의미하는 String을 입력으로 받는다. 출석기록은 3가지 문자로만 이루어져 있다


A : 결석

L : 지각

P : 출석


결석이 한번을 넘거나 연속으로 두번 넘게 지각하는 경우가 없어야만 상을 받는다. 해당 학생이 상을 받을 수 있는지 없는지 리턴하라.



이 문제는 정규식을 이용해 1줄의 코드로 풀 수 있다. 정규식에 대해 잘 모른다면 아래 포스팅을 참고하자. {n}은 n번 반복이라는 뜻이다.


2019/03/30 - [프로그래밍문제풀기] - JAVA 정규표현식 (Regular expression)



1
2
3
4
5
6
class Solution {
    public boolean checkRecord(String s) {
        
        return !s.matches(".*A.*A.*|.*L{3}.*");
    }
}
cs






두번째 방법은 배열을 탐색하면서 A가 1번을 넘는지, L이 2번 넘게 연속인지 확인하는 것이다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution {
    public boolean checkRecord(String s) {
        
        int absent=0;
        int continuousLate=0;
        
        for(char c : s.toCharArray()) {
            
            if(c=='A') absent++;
            
            if(c=='L') continuousLate++else continuousLate=0;
            
            if( absent>1 || continuousLate>2 ) return false;
            
        }
        return true;
    }
}
cs



LeetCode 문제 중 난이도 EasyMove Zeroes이다. 문제 링크는 포스팅의 맨 마지막에 추가하였다. 언어는 Java를 사용했다.



  문제해석


주어진 배열 nums의 모든 0 값들을 뒤쪽으로 이동시키면서 0이 아닌 값의 순서는 그대로 유지하는 함수를 작성해라.

* nums의 복사본인 새로운 배열을 생성하지 않고 nums배열에서 작업한다

* 전체 연산의 수를 최소화한다




첫번째 방법은 가장 처음으로 0이 나오는 값의 인덱스를 구한다. 그리고 0의 인덱스값 뒤에 오는 요소들 중 처음으로 나오는 0이 아닌 숫자를 0의 인덱스에 넣고 숫자가 있던 자리는 0으로 바꾼다. 배열의 값이 0인 인덱스들에 같은 행위를 반복한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Solution {
    public void moveZeroes(int[] nums) {
        
        int indexOfZero=-1;
        
        //맨처음 0을 찾아서 index값 가져옴
        for(int i=0 ; i<nums.length ; i++){
            if(nums[i]==0){
                indexOfZero=i;
                break;
            }
        }
        
        //0이 없으면 그대로 리턴
        if(indexOfZero==-1return;
        
        //0이 있는곳으로 뒤에서 0이 아닌수를 가져오고 index를 하나 늘린다(반복)
        for(int i=zeroIndex ; i<nums.length ; i++){
            if(nums[i]==0continue;
                nums[indexOfZero]=nums[i];
                nums[i]=0;
                indexOfZero++;
        }
    }
}
cs

시간복잡도는 O(n), 공간복잡도는 O(1)이다. 이 방법은 경우에 따라 불필요한 추가연산을 하게 되는 경우가 있다. 아래 예시를 보자.


만일 nums가 [1, 0, 2, 4, 5, 0]라고 가정해보자. 그럼 연산순서는 아래와 같을 것이다.

[1, 0, 2, 4, 5, 0] -> [1, 2, 0, 4, 5, 0] -> [1, 2, 4, 0, 5, 0] -> [1, 2, 4, 5, 0, 0]

nums[2]에 0을 넣었다가 다시 4로 바꾸고 nums[3]도 0을 넣었다가 다시 5로 바꾼다.





두번째 방법은 배열을 탐색하면서 0이 아닌 숫자들을 앞에서부터 순서대로 집어넣고 그 뒤를 0으로 채우는 것이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
    public void moveZeroes(int[] nums) {
        
        int index=0;
        
        //0이 아닌 숫자를 찾아서 앞에서부터 하나씩 채운다
        for(int i=0 ; i<nums.length ; i++){
            if(nums[i]!=0){
                nums[index]=nums[i];
                index++;
            }
        }
        
        //index뒤를 전부 0으로 바꾼다
        while(index<nums.length){
            nums[index]=0;
            index++;
        }
    }
}
cs

이렇게 하면 특정 위치의 값을 두번씩 바꾸는 일은 없겠지만 0의 갯수가 많을수록 0을 채워넣는 연산이 중복되는 경우가 생긴다(0을 또다시 0으로 채우는 경우). 이 방법도 동일하게 시간복잡도는 O(n), 공간복잡도는 O(1)이다.


문제출처 - https://leetcode.com/problems/move-zeroes/




LeetCode 문제 중 난이도 EasyContains Duplicate이다. 문제 링크는 포스팅의 맨 마지막에 추가하였다. 언어는 Java를 사용했다.



  문제해석


정수 배열을 입력값으로 받아 해당 배열이 중복값을 포함하고 있는지 판별하라.

아무 값이나 배열 내에서 두번 이상 나타나는 값이 있다면 true를 리턴하고 모든 요소가 유일하다면 false를 리턴해라.







첫번째 방법은 배열을 정렬한 후 앞뒤 값을 비교하는 것이다. 이전에 포스팅한 Single Number 문제의 첫번째 풀이법과 원리가 같다.


2019/03/16 - [프로그래밍문제풀기] - [코딩연습] Single Number 하나뿐인 숫자 찾기




1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Solution {
    public boolean containsDuplicate(int[] nums) {
        
        Arrays.sort(nums);
        
        for(int i=0 ; i<nums.length-1 ; i++){
            //앞뒤 값이 같은게 나오면 true리턴
            if(nums[i] == nums[i+1]) return true;
        }
        
        //for문을 빠져나와 전체 배열을 다 돌때까지 중복이 없으면 false리턴
        return false;
    }
}
cs


정렬하는데 드는 시간 O(nlogn), 탐색하는데 드는 시간 O(n)으로 시간복잡도는 O(nlogn)이고 추가적인 메모리 사용이 없으므로 공간복잡도는 O(1)이다.





두번째 방법은 Set 자료구조를 이용하는 것이다. Set은 중복된 데이터를 허용하지 않는 집합이다. 만약 nums에 중복된 값이 있다면 nums의 길이와 numset의 사이즈가 다를 것이다.

ex) nums = [3,7,7,8,6] 일 경우 nums.length=5, numSet.size()=4


1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution {
    public boolean containsDuplicate(int[] nums) {
        
        Set<Integer> numSet = new HashSet<>();
        
        for(int i=0 ; i<nums.length ; i++){
            numSet.add(nums[i]);
        }
        
        //배열의 길이와 배열의 요소를 모아놓은 집합의 크기가 다르면 true, 같으면 false 리턴
        return nums.length != numSet.size();
    }
}
cs



이 방법은 배열을 한번만 탐색하므로 시간복잡도는 O(n)이지만 numSet이라는 추가적인 공간을 사용하므로 공간복잡도는 O(n)이다.





문제 출처 - https://leetcode.com/problems/contains-duplicate/






LeetCode 문제 중 난이도 EasySymmetric Tree이다. 문제 링크는 포스팅의 맨 마지막에 추가하였다. 언어는 Java를 사용했다.





  문제해석

주어진 이진 트리를 가지고 해당 트리가 거울에 비친 자신과 같은지(가운데를 중심으로 대칭인지) 판별하라.








트리는 모든 노드들이 연결되어있고 순환이 존재하지 않는 그래프이다.

나무(tree)를 거꾸로 그린 모양의 계층구조를 생각해보자. 트리(tree) 자료구조는 뿌리(root node)에서 시작해 가지가 뻗어 나가며 맨 끝에는 잎(leaf node)이 달려 있다. 우리가 잘 아는 트리구조가 있는데 바로 회사의 조직도와 컴퓨터 디렉토리이다.








아래 그림은 이진 트리(binary tree)의 예이다. 예시를 보며 몇가지 기본적인 트리 용어를 알아보자.


* 이진트리(binary tree) : 트리 중에서 각 노드의 자식 노드의 수가 2개 이하인 트리



Node(A,B,C...J) : 트리의 구성요소에 해당하는 요소들


Root Node(A) : 최상위 노드


Parent Node : 어떤 노드의 상위 노드

A는 B와 C의 부모노드이고 B와 C도 각각 D&E, F&Gd의 부모노드이다


Child Node : 어떤 노드의 하위 노드

F와 G는 C의 자식노드이고 H와 I는 E의 자식노드이다


Subtree : 어떤 노드의 부모 노드의 집합

D의 조상은 B,A이고 J의 조상은 G,C,A이다


Descendant of a node : 어떤 노드의 자식노드들의 집합

C의 자손은 F,G,J이고 A 자손은 자기자신을 제외한 전체 노드들이다


Leaf Node(D,H,I,F,J) : 자식노드가 존재하지 않는 노드


Subtree : 어떤 트리의 안에 있는 작은 트리

트리 T의 서브트리 S는 T의 노드 중 하나와 그의 자손들로 이루어진 트리


Depth of a node : 어떤 노드의 루트노드까지의 조상의 수

루트노드의 depth는 0이고 G의 depth는 2이다


Height of a tree : 해당 트리가 가진 노드들의 depth중 최댓값






다시 문제로 돌아가보자. 트리가 좌우 대칭이려면 루트노드를 중심으로 왼쪽 서브트리를 좌우대칭한 것이 오른쪽 서브트리와 같아야 한다. 그러려면 왼쪽 서브트리의 왼쪽 자식노드오른쪽 서브트리의 오른쪽 자식노드의 값이 같아야 하고 왼쪽 서브트리의 오른쪽 자식노드오른쪽 서브트리의 왼쪽 자식노드의 값이 같아야 한다.



같은방식으로 자손노드들을 리프노드까지 탐색한다. 코드로 나타내면 다음과 같다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
    public boolean isSymmetric(TreeNode root) {
        
        return isMirror(root,root);
    }
    
    public boolean isMirror(TreeNode t1, TreeNode t2) {
        
        //t1과 t2가 둘다 null이면 true
        if(t1 == null && t2 == nullreturn true;
        
        //t1,t2중에 하나만 널이면 양쪽이 같지 않으므로 false
        if(t1 == null || t2 == nullreturn false;
        
        //t1과 t2의 값이 달라도 false
        if(t1.val != t2.val) return false;
        
        return isMirror(t1.left,t2.right) && isMirror(t1.right,t2.left);
    }
}
cs


13번째 줄의 (t1 == null || t2 == null)는 위에서 이미 둘다 null인 경우를 체크했으므로 t1이나 t2가 둘중 하나만 null인 경우를 체크한다.



이 방법의 시간복잡도는 O(n)이고 공간복잡도의 worse case는 트리가 일직선으로 이루어져 Height가 O(n)인 경우이므로 O(n)이다.




문제 출처 - https://leetcode.com/problems/symmetric-tree/




LeetCode 문제 중 난이도 EasyUnique Morse Code Words 이다. 문제 링크는 포스팅의 맨 마지막에 추가하였다. 언어는 Java를 사용했다.



  문제 해석

국제 모스 부호는 다음과 같이 각 알파벳 문자가 일련의 점과 대시에 매핑되는 표준 인코딩을 정의한다.

"a"는 ".-", "b"는 "-...", "c"는 "-.-." 등등..

편의를 위해서 알파벳 전체 26문자의 표는 아래를 참고한다.

[".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--.."]

주어진 단어들의 리스트에서 각 단어들은 각각의 알파벳의 모스부호를 연결해서 쓰여질 수 있다. 예를 들어 "cba"는 "-.-." + "-..." + ".-"인 "-.-.-....-"가 된다. 이렇게 이어진것을 단어 변환이라고 부른다. words중에서 그런 서로 다른 변환의 가짓수를 리턴하라.


* 원본문제의 모스부호 변환 예시가 살짝 틀렸는데 그냥 무시하면 된다. 어쨌든 입력값 words을 모스부호로 변환시 나오는 가짓수를 리턴하면 된다.



이 문제는 그냥 직관적으로 풀면 된다. 단어를 모스부호로 나타냈을 때 나올 수 있는 경우의수가 몇가지인지 알기 위해서는 먼저 input으로 받은 words를 모스부호 문자표를 이용해서 변환해야 한다. 그 다음 변환된 결과들 중에서 중복을 제거한 후 총 나오는 가짓수가 몇개인지 세면 된다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Solution {
    public int uniqueMorseRepresentations(String[] words) {
        String[] morse = {".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--",
                            "-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--.."};
        
        //모스부호화 된 words를 저장할 배열
        String[] encoded = new String[words.length];
        
        //알파벳을 모스부호로 치환함
        for(int i=0 ; i<words.length ; i++){
            for(int j=0 ; j<words[i].length() ; j++){
                encoded[i]=encoded[i]+morse[words[i].charAt(j)-'a'];
            }
        }
        
        //중복값을 제거하기 위해 Set에 담는다
        Set<String> codeSet = new HashSet<>();
        for(int i=0 ; i<encoded.length ; i++){
            if(!codeSet.contains(encoded[i])) codeSet.add(encoded[i]);
        }
        
        return codeSet.size();
    }
}
cs


encoded라는 새로운 배열을 생성해서 words의 단어들을 모스부호화 시켜 저장했다. 그 다음 words를 Set 자료형에 담아 중복값을 제외한다. 마지막으로 Set의 사이즈를 리턴하면 된다. 

12번째줄의 words[i].charAt(j)-'a' 는 알파벳의 아스키코드를 이용한 것이다. 알파벳의 모스부호가 morse배열에 a부터 z까지 순서대로 들어가 있으므로 해당 알파벳-'a'를 하면 그 알파벳이 a부터 몇 번째 뒤에 있는지 알 수 있다. 지난번에 풀었던 Valid Anagram 문제의 두번째 풀이와 같은 원리이다.


2019/04/09 - [프로그래밍문제풀기] - [코딩연습] Valid Anagram 유효한 애너그램인지 체크하기



위 코드의 시간복잡도는 O(S), 공간복잡도는 O(S)이다. 여기서 S는 input인 words배열에 들어있는 단어들의 길이의 합을 말한다.



문제 출처 - https://leetcode.com/problems/unique-morse-code-words/




LeetCode 문제 중 난이도 EasyLargest Number At Least Twice of Others이다. 문제 링크는 포스팅의 맨 마지막에 추가하였다. 언어는 Java를 사용했다.



  문제해석

정수배열인 nums는 딱 하나의 가장 큰 값을 가지고 있다.

다른 모든 숫자들보다 두배이상 큰 가장 큰 수가 있다면 인덱스 값을 리턴하라. 그렇지 않으면 -1을 리턴한다.





가장 큰 값이 모든 값보다 두배 이상 큰지 보려면 두번째로 큰 값보다 두배 이상 큰지 확인하면 된다. 배열을 돌면서 가장 큰 값(largest)과 두번째로 큰 값(secondLargest)의 인덱스를 탐색한다.


맨 처음에 0,1을 넣고 nums[2]부터 돌면서 i가 largest보다도 큰 가장 큰 값이면 largest의 값을 secondLargest에 넣고 i의 값을 largest에 넣는다. largest보다는 크지 않지만 secondLargest보다 크면 secondLargest를 i로 바꿔준다. 마지막까지 배열을 탐색한 후 nums[secondLargest]*2≤를 만족하면 largest를 리턴하고 아니면 -1을 리턴한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Solution {
    public int dominantIndex(int[] nums) {
        
        if(nums.length==1return 0;
        
        //비교를 위해 첫 두 배열의 값을 넣어주고 시작
        int largest=0;
        int secondLargest=1;
        if(nums[0]<nums[1]){
            largest=1;
            secondLargest=0;
        }
        
        //nums[i]가 largest보다크면 바꾸고 largest보단안커도 secondLargest보다크면 바꿈
        for(int i=2 ; i<nums.length ; i++){
            if(nums[i]>nums[largest]){
                secondLargest=largest;
                largest=i;
            }else if(nums[i]>nums[secondLargest]) secondLargest=i;
            
        }
 
        //largest가 secondLargest*2 보다 크거나 같으면 인덱스값 반환,아니면 -1
        return nums[largest]>=nums[secondLargest]*2 ? largest : -1 ;
    }
}
cs

마지막 리턴값의 A ? B : C 는 삼항연산자라고 부르고 A가 참이면 B를, A가 거짓이면 C를 반환한다.


배열을 한번 전체탐색하고 추가적인 메모리는 사용하지 않으므로 이 방법의 시간복잡도는 O(n), 공간복잡도는 O(1)이다.


문제 출처 링크 - https://leetcode.com/problems/largest-number-at-least-twice-of-others/



LeetCode 문제 중 난이도 EasyFind the Town Judge이다. 문제 링크는 포스팅의 맨 마지막에 추가하였다. 언어는 Java를 사용했다.


  문제해석

마을엔 1부터 N으로 표기되는 N명의 사람들이 있다. 이들 중 한사람이 비밀스러운 마을 판사라는 소문이 있다.

만약 마을판사가 존재한다면

1. 마을판사는 아무도 신뢰하지 않는다.

2. 모든사람들(마을판사를 제외한)은 마을판사를 신뢰한다.

3. 위의 1,2 조건을 만족하는 사람은 딱 한명 뿐이다.

입력으로 trust 배열이 주어진다. trust[i]=trust[a,b]는 a가 b를 신뢰한다는 의미이다.

마을판사가 존재한다면 그사람의 번호를 리턴하고 존재하지 않는다면 -1을 리턴하라.

* 1 ≤ N ≤ 1000

* trust.length ≤ 10000

* trust[i] are all different

* trust[i][0] != trust[i][1]

* 1 ≤ trust[i][0], trust[i][1] ≤ N




마을판사가 존재하고 x라고 하자. 모두가 x를 신뢰해야 하므로 ①trust배열 안에 [1,x],[2,x],[3,x]....[n,x]가 전부 있어야 하고 x는 아무도 신뢰하지 않으므로 ②[x,n]은 있으면 안된다.


이 값을 계산하기 위해 tsum[N] 배열을 만들어서 tsum[x-1]에 x를 믿는 사람들의 번호의 합을 저장한다. x가 마을판사이려면 자기자신인 x를 제외한 1~N의 사람들이 전부 x를 신뢰해야 하므로 tsum[x-1][1]은 1~N의 합-x 어야 한다. 그리고 x는 아무도 믿지 않으므로 [x,b]일 때 tsum[x-1]의 값에 -1을 집어넣는다.

이렇게 하면 x를 제외한 모두가 x를 믿는다고 해도 tsum[x-1]의 값은 1~N-x보다 작아진다. -1대신에 아무 음수 또는 N(N+1)/2보다 큰값을 집어넣어도 된다. 코드는 다음과 같다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Solution {
    public static int findJudge(int N, int[][] trust) {
        int[] tsum = new int[N];
        int nsum = N*(N+1)/2;
        
        //[a,b]이면 tsum[b-1]에 a를 더함
        for(int i=0 ; i<trust.length ; i++){
            tsum[trust[i][1]-1= tsum[trust[i][1]-1+ trust[i][0];
            tsum[trust[i][0]-1= -1;
        }
        
        //tsum[x-1]이 1~N의 합과 같으면 x 리턴
        for(int i=0 ; i<tsum.length ; i++){
            if(tsum[i]+i+1 == nsum){
                return i+1;
            }
        }
        
        //그런 값이 없으면 -1 리턴
        return -1;
    }
}
 
cs


이 방법의 시간복잡도는 O(n) 공간복잡도도 O(n)이다.


문제 출처 - https://leetcode.com/problems/find-the-town-judge

+ Recent posts