2019년 7월 26일 금요일

java Varargs (가변인자)




* Varargs (가변인자)

 메소드의 매개변수의 개수를 동적으로 지정할 수 있는 방법이 있는데 메소드 오버로드를 하거나 가변인자(Variable argument)를 사용할 수 있다.

아래 코드는 add 메소드의 매개변수를 가변인자로 받아들여, int형 타입의 파라미터들의 개수를 동적으로 넣을 수 있다.




아래는 직접 작성한 코드이다.
class Add {
    void add(int... args){ //타입...변수명으로 사용한다.
        int sum = 0;
        String s = "";
        int[] arr = args; //args는 배열이므로 for문으로 이용해 값 하나 하나에 접근이 가능하다.
        for(int n : args)
            sum += n;
        
        for(int i = 0 ; i < arr.length; i++){
            s += arr[i];
            if(arr.length-1 == i)
                s += "=";
            else
                s += "+";
        }
        System.out.println(s+sum);
    }
}

hackerrank의 답안이 간결하여 가져왔다.
class Add{
    public void add(int ...arr){
        int sum = 0;
        String s = "";
        for(int i = 0; i < arr.length; i++){
            sum += arr[i];
            s += arr[i];
            if(i < arr.length-1) //마지막 순환이 아닌 경우에만 +기호를 붙인다.
                s += "+";
        }
        s += "=" + sum;
        System.out.println(s);
    }
}

2019년 7월 24일 수요일

Python 3 Operator




* Python 3 Operator



연산자설명예제
+더하기5 + 3
-빼기5 - 3
*곱하기5 * 3
**거듭제곱5 ** 3
/나누기, 값이 실수(float)형으로 반환된다.5 / 3
//나누기, 값이 정수(integer)형으로 반환된다. 5 // 3 



Java Priority Queue (우선순위큐)




* Priority Queue, 우선순위 큐

우선순위큐는 말 그대로 큐의 성질을 가졌으나, 각 데이터가 우선순위를 갖고 있어 우선순위가 높은 순서대로 나오게 된다. 
 만약 우선순위가 동일하다면 큐에서 그들의 순서에 의해 처리된다.
 아래 문제는 이미 구현되어져 있는 자바 클래스인 PriorityQueue를 가지고 원하는 우선순위를 구현할 수 있는지에 대한 문제이다. 
 어떤 객체의 내부속성에 대해 특별한 기준으로 정렬을 하고 싶다면 Comparable 인터페이스의 compareTo 메소드를 구현하면 된다.
 아래 Student 클래스의 예시에서 우선순위대로 정렬의 기준을 구현하였다.
CGPA 점수가 높은 것이 우선순위가 더 높다고 하였으므로,비교대상점수가 더 높을 경우 원래라면 -1을 리턴하여 앞이 더 앞서다고 나타내야겠지만 1을 return 함으로써 그 순서가 역(내림차순)으로 정렬을 해야한다는 점을 알려준다.
이 부분이 이해가 되지 않을 경우 예전 게시글을 참고한다.

* 참고 : compareTo

compareTo 메소드는 매번 헷갈리는 부분이 있어 문제에 등장할 때마다 정리하게 된다.😓

결론은 정렬 기준의 순서대로 PriorityQueue에서 poll() 하는 경우 우선순위가 높은 것부터 나오게 된다.  




import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.*;
/*
 * Create the Student and Priorities classes here.
 */
class Student implements Comparable{
    int id;
    String name;
    double cgpa;

    public Student(int id, String name, double cgpa){
        this.id = id;
        this.name = name;
        this.cgpa = cgpa;
    }
    public int getID(){
        return id;
    }
    public String getName(){
        return name;
    }
    public double getCGPA(){
        return cgpa;
    }
    @Override
    public int compareTo(Student target){
        if(this.cgpa < target.getCGPA()){
            return 1;
        }else if(this.cgpa == target.getCGPA()){
            if( this.name.compareTo(target.getName()) < 0) { //String의 비교는 String에 내장된 것을 사용.
                return -1; //이름은 오름차순으로 정렬
            }else if( this.name.compareTo(target.getName()) == 0 ){
                if(this.id < target.getID()){
                    return -1;
                }else if(this.id == target.getID()){
                    return 0;
                }else{
                    return 1;
                }

            }else{
                return 1;
            }
        
        }else{
            return -1;
        }
    }

}

class Priorities{
    PriorityQueue q;

    List getStudents(List events){
        q = new PriorityQueue();
        List list = new ArrayList();
        //System.out.println(events.size());

        for(int i = 0 ; i < events.size();i++){
            String event = events.get(i);
            String[] eArr = event.split(" ");
            if(eArr[0].equals("SERVED")){
                q.poll();

            }else{
                q.offer(new Student(Integer.parseInt(eArr[3]),eArr[1],Double.parseDouble(eArr[2])));
            }
        }
            
        while(q.size()>0){
            list.add(q.poll());
        }
    
        return list; 
    }

}

public class Solution {
    private final static Scanner scan = new Scanner(System.in);
    private final static Priorities priorities = new Priorities();
    
    public static void main(String[] args) {
        int totalEvents = Integer.parseInt(scan.nextLine());    
        List events = new ArrayList<>();
        
        while (totalEvents-- != 0) {
            String event = scan.nextLine();
            events.add(event);
        }
        
        List students = priorities.getStudents(events);
        
        if (students.isEmpty()) {
            System.out.println("EMPTY");
        } else {
            for (Student st: students) {
                System.out.println(st.getName());
            }
        }
    }
}

2019년 7월 17일 수요일

Java Dequeue




* Dequeue 

Dequeue deck이라고 발음하기도 하는데, 양 끝이 열려있는 통로처럼 생긴 자료구조이다.
양 끝이 열려 있어 dequeue에 저장되어 있는 데이터들은 head와 tail 양 쪽에서 꺼내고 넣을 수 있는 특징이 있다.

참조: Dequeue API



 아래는 Hackerrank java Dequeue문제이다. 

n개의 int 값이 주어지며, 그 데이터들의 서브 배열의 길이는 m이다. m개의 서브 배열을 만들어가면서 서브 배열들 속에서 유니크한 데이터들의 수의 최대값을 구하는 문제이다.  


입력 예시)
6  =>n
3  => m
5 3 5 2 3 2 =>n개의 데이터

1번째 subArray: [5, 3, 5] - 유니크 데이터 개수: 2
2번째 subArray: [3, 5, 2] - 유니크 데이터 개수: 3
3번째 subArray: [5, 2, 3] - 유니크 데이터 개수: 3
4번째 subArray: [2, 3, 2] - 유니크 데이터 개수: 2

최대값은 3이 된다.


import java.util.*;
    public class test {
        public static void main(String[] args) {
            Scanner in = new Scanner(System.in);
            Deque deque = new ArrayDeque();
            int n = in.nextInt();
            int m = in.nextInt();

            int max = 0;
            Set set = new HashSet(); //유니크한 데이터만 저장하기 위한 HashSet

            for (int i = 0; i < n; i++) {
                int num = in.nextInt();
                deque.add(num); //dequeue에 값을 넣으면서
                set.add(num); //set에도 값을 넣는다.
                if(deque.size() == m){ //서브배열만큼 넣었을 때
                    if(max < set.size()){ 
                        max = set.size();
                    }
                    int first = deque.removeFirst(); //dequeue에서 첫번째 데이터를 지우고 그 값 저장한다.
                    if(!deque.contains(first)) set.remove(first); //point

                }
            }
            
            System.out.println(max);

        }
    }

포인트는 이 부분이다.

if(!deque.contains(first)) set.remove(first); 

dequeue에 first 값이 존재하지 않는다면, 그 값을 set에서 삭제한다.
dequeue에 첫 번째 값이 존재하지 않는다는 말은 first 값과 중복 된 값이 없다는 뜻이다. 
 즉 중복된 값이 없으므로 set 집합에서도 지워주어야 한다.
first 값을 삭제하고 난 후에도 first 값이 dequeue 안에 또 존재한다면, set에서는 삭제 처리를 하지 않아도 된다. 
set은 유니크한 데이터만 존재하므로 first 값이 이미 삭제 된 것이나 마찬가지이기 때문이다.

2019년 7월 12일 금요일

깊이 우선 탐색 (DFS, Depth-First Search)




DFS 깊이우선 탐색 알고리즘을 이용하여 풀수 있는 문제이다.
하나의 위치에서 갈 수 있는 모든 가능성에 대한 조사를 하고, 다음 위치로 넘어간다. 

* 문제 이해

n 길이의 1차 배열 arr 이 주어지고, arr[0]은 무조건 0으로 시작한다.  leap은 점프할수 있는 칸수이다.

1. 뒤로 이동
 * 만약 i-1이 존재하고, 그 인덱스의 값이 0이라면 i-1로 이동할 수 있다.
2. 앞으로 이동
 * arr[i+1]이 0이라면 한 칸을 앞으로 이동할 수 있다.
 * arr[i+leap]이 0이라면 i+leap으로 이동할 수 있다.
 * 만약 n-1에 위치하거나 i+leap>=n인 경우 win 이며 그 외는 fail이다.
 즉 인덱스 i부터 i+1 ,i-1, i+leap 번째 배열의 값이 0인 곳으로만 이동하면서 배열의 마지막에 도달하거나, 배열의 길이보다 높게 뛸 수 있으면 게임에서 이기게 된다.

문제를 풀기 위해서, 현재 위치에서 이동할 수 있는 조건들을 깊이 탐색을 해야하는 과정이 필요한데 이것은 재귀호출을 이용하여 탐색할 수 있다. 
 또한 다음 위치로 넘어가기 전에 현재 위치는 탐색을 완료했다는 표시를 반드시 해야 한다.
 그렇지 않으면 현재 위치로 다시 돌아올 경우 동일하게 탐색을 또 하기 때문에 무한루프에 빠지게 된다.



public class Solution {

     public static boolean canWin(int leap, int[] game) {
        return isSolvable(leap, game, 0); //뛸 수 있는 숫자, 배열, 시작 인덱스
    }

    private static boolean isSolvable(int leap, int[] game, int i) {
        // Base Cases
        if (i >= game.length) { //현재 위치의 인덱스가 전체 배열의 길이보다 같거나 크면
            return true; //게임에서 이김
        } else if (i < 0 || game[i] == 1) { //i가 0보다 작거나, 현재 위치의 배열 값이 1이면
            return false; //게임에서 짐
        }

        game[i] = 1; // (핵심) 현재 체크(방문)한 배열 위치의 값을 1로 마킹한다.

        // 재귀호출.
        // 현 위치에서 점프하거나, 앞으로 한칸을 가거나, 뒤로 한칸 가는 모든 상황을 체크한다. 
        // 그 중 하나라도 true를 반환한다면 게임에서 이긴다.
        // 3가지 가능한 케이스가 재귀를 돌면서 그 안에서 또 각 위치에서 세가지 케이스를 확인하므로 모든 조건에 대한 탐색이 가능하게 한다.
        return isSolvable(leap, game, i + leap) ||
                isSolvable(leap, game, i + 1) ||
                isSolvable(leap, game, i - 1);
    }

    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int q = scan.nextInt();
        while (q-- > 0) {
            int n = scan.nextInt();
            int leap = scan.nextInt();
            
            int[] game = new int[n];
            for (int i = 0; i < n; i++) {
                game[i] = scan.nextInt();
            }

            System.out.println( (canWin(leap, game)) ? "YES" : "NO" );
        }
        scan.close();
    }
}