Strong Root

난이도 ★


문제를 보시려면 여기를 클릭





문제 요약

 A배열을 K번만큼 오른쪽으로 shift하면 됩니다





힌트

 K번만큼 실제로 일일이 이동하지 말고, 최종 위치로 한번에 일괄 이동합니다





이하는 코드입니다.


1
2
3
4
5
6
7
8
9
10
11
public int[] solution(int[] A, int K) {
    int[] ret = new int[A.length];
 
    for (int i = 0; i < A.length; i++) {
        int idx = (i + K) % A.length;
 
        ret[idx] = A[i];
    }
 
    return ret;
}
cs


난이도 ★


문제를 보시려면 여기를 클릭





문제 요약

 총 홀수번 등장하는 숫자가 딱 1종류 있는데 그걸 리턴하면 됩니다 





힌트

 자료구조 문제이며, 등장 횟수 측정의 부하를 줄이는 것이 핵심입니다 (Hash 사용을 추천)





이하는 코드입니다.


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
public int solution(int[] A) {
    Map<Integer, Integer> countMap = new HashMap<>();
 
    for (int i = 0; i < A.length; i++) {
        increaseCount(countMap, A[i]);
    }
 
    for (Integer key : countMap.keySet()) {
        if (countMap.get(key) % 2 != 0) {
            return key;
        }
    }
 
    return -1;
}
 
private void increaseCount(Map<Integer, Integer> countMap, int targetNum) {
    Integer target = countMap.get(targetNum);
 
    if (target == null) {
        countMap.put(targetNum, 1);
    }
    else {
        countMap.put(targetNum, target + 1);
    }
}
cs

난이도 ★


문제를 보시려면 여기를 클릭



 

힌트

 그냥 빼먹는 것 없이 반복문을 잘 돌면 됩니다




이하는 코드입니다.


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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public int solution(int N) {
    String biStr = Integer.toBinaryString(N);
    int firstOneIndex = getNextOneIndex(biStr, 0);
 
    if (firstOneIndex < 0) {
        return 0;
    }
 
    int maxGap = 0;
 
    while (true) {
        int nextOneIndex = getNextOneIndex(biStr, firstOneIndex + 1);
 
        if (nextOneIndex < 0) {
            break;
        }
 
        int gap = nextOneIndex - firstOneIndex - 1;
 
        if (gap > maxGap) {
            maxGap = gap;
        }
 
        firstOneIndex = nextOneIndex;
    }
 
    return maxGap;
}
 
private int getNextOneIndex(String biStr, int startIndex) {
    int nextOneIndex = -1;
 
    for (int i = startIndex; i < biStr.length(); i++) {
        char c = biStr.charAt(i);
 
        if (c == '1') {
            nextOneIndex = i;
            break;
        }
    }
 
    return nextOneIndex;
}
cs



비밀번호 저장시


1. 충분히 긴 길이의 랜덤 salt 를 생성한다. (java.security.SecureRandom 사용할 것)


2. 생성된 salt 에 타깃 pw 를 붙이고 해싱한다.


3. salt 와 결과 hash 를 둘다 유저 테이블에 있는 각각의 컬럼에 나란히 저장한다.




비밀번호 검증시


1. 유저 테이블에서 해당 유저의 salt 와 결과 hash 를 가져온다.


2. salt 뒤에 검증할 pw 를 붙이고 같은 해싱 기법으로 해싱한다.


3. hash 결과를 비교하여 일치하면 true, 아니면 false




주의


1. salt 는 유저마다, 패스워드마다 고유해야 한다. (The salt needs to be unique per-user per-password.)


2. 한번이라도 사용된 salt 는 절대 재사용하면 안된다.


3. salt 의 길이는 충분히 길어야 한다. 결과 hash 와 같은 길이로 하는 것이 가장 좋다.


4. salt 값은 유저 테이블에 결과 hash 와 나란히 저장되어야 한다.






출처


https://crackstation.net/hashing-security.htm



문제


출력 결과는 무엇일까요?


1
2
3
4
5
6
7
8
9
10
11
public class Person {
    public String name = "CGun";
    
    public String getName() {
        return name;
    }
    
    public int getAge() {
        return 29;
    }
}
cs



1
2
3
4
5
6
7
public class Man extends Person {
    public String name = "CGun2";
 
    public int getAge() {
        return 30;
    }
}
cs



1
2
3
4
5
6
7
public class Test {
    public static void main(String[] args) {
        Man m = new Man();
        
        System.out.println(m.getName() + ", " + m.getAge());
    }
}
cs
















정답







해설


틀린 분 많으시죠?


상속시, 함수 오버라이딩은 많이들 아시겠지만 변수 오버라이딩에 대해서는 모르는 분이 많으실 겁니다.



변수는 오버라이딩되지 않습니다. (자식에 의해 덮어써지지 않고 계속 살아있습니다)


재미있는 결과를 더 알려드리겠습니다.



1
2
3
4
Man m = new Man();
 
System.out.println(m.name);    // CGun2
System.out.println(((Person) m).name);    // CGun
cs


3라인은 Man 의 name 값인 "CGun2" 가 출력되며,


4라인은 Person 의 name 값인 "CGun" 이 출력됩니다.



문제


출력 결과는 무엇일까요?


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
27
28
29
30
public class Test {
    public static void main(String[] args) {
        int[] arr = new int[2];
 
        try {
            arr[0= 0;
            System.out.println(arr[0]);
 
            arr[1= 1;
            System.out.println(arr[1]);
 
            arr[2= 2;
            System.out.println(arr[2]);
        }
        catch (NullPointerException e) {
            System.out.println(3);
        }
        catch (ArrayIndexOutOfBoundsException e) {
            System.out.println(4);
        }
        catch (Exception e) {
            System.out.println(5);
        }
        finally {
            System.out.println(6);
        }
 
        System.out.println(7);
    }
}
cs
















정답







해설


1. Exception 발생 즉시 try 문은 건너뛰고 catch 문으로 간다.


2. catch 가 여러개이면 맨 위부터 현재 Exception 을 잡아줄 수 있는지 체크하며,


   잡아줄 수 있는 최초의 catch 문만 수행하고 finally 로 간다.


3. finally 문이 있다면 수행 후 빠져나가고 프로그램은 아래로 계속 진행된다.



문제


출력 결과는 무엇일까요?


1
2
3
4
5
6
7
8
9
10
11
12
13
public class Person {
    private String name;
    private int age;
    
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    public int getAge() {
        return age;
    }
}
cs



1
2
3
4
5
6
7
8
9
10
11
12
public class Test {
    public static void main(String[] args) {
        Person p1 = new Person("CGun"29);
        Person p2 = p1;
        
        p1.age = 30;
        p2.name = "CGun2";
        
        System.out.println(p1.name + ", " + p1.age);
        System.out.println(p2.name + ", " + p2.age);
    }
}
cs
















정답







해설


Person p2 = p1; 실행시에 일어나는 동작을 아는 것이 중요하다.


p1 객체를 복사하여 p2 에 할당하는 것이 아니라,


p1 객체와 같은 곳을 p2 가 가리키게 하는 구문이다.


즉,  reference 값만 복사된다는 뜻이며 결국 p1 과 p2 가 같은 객체를 가리키고 있다는 뜻이다.



문제


출력 결과는 무엇일까요?


1
2
3
4
5
6
7
8
9
10
11
12
13
public class Person {
    private String name;
    private int age;
    
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    public int getAge() {
        return age;
    }
}
cs



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Test {
    static void increase(Person p, int weight) {
        p.age = 30;
        weight = 70;
    }
 
    public static void main(String[] args) {
        Person p = new Person("CGun"29);
        int weight = 60;
        
        increase(p, weight);
        
        System.out.println(p.age + ", " + weight);
    }
}
cs
















정답







해설


객체 변수는 Call by Reference 로 동작하므로 의도대로 값이 들어갔지만,


일반 변수는 Call by Value 로 동작하므로 increase 함수 내부 변수만 값이 증가하며

해당 함수가 종료되면 내부 변수는 증발한다.