728x90

문제

숫자를 입력 받아 0이 입력으로 들어오면 이전 숫자를 지우고

최종적으로 남아 있는 값들의 합을 구하라

 

접근 방식

스택에 입력값을 계속 push하면서 입력값이 0인 경우에만

저장하지 않고 가장 최근에 저장된 값을 pop 해준다.

 

합은 스택을 forEach문을 돌리거나 pop으로 꺼내면서 더해준다.

 

풀이

public class Main {

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

		int k = Integer.parseInt(br.readLine());

		Stack<Integer> stack = new Stack<>();

		for (int i = 0; i < k; i++) {
			int number = Integer.parseInt(br.readLine());

			if (number == 0) {
				stack.pop();
			} else {
				stack.push(number);
			}
		}

		int sum = 0;

		for (int s : stack) {
			sum += s;
		}

		bw.write(sum + "");
		bw.flush();
	}
}

'Java > Algorithms' 카테고리의 다른 글

[백준] 2493번 : 탑  (0) 2023.10.03
[백준] 1874번 : 스택 수열  (0) 2023.10.02
[백준] 10828번 : 스택  (0) 2023.10.01
[백준] 1158번 : 요세푸스 문제  (0) 2023.10.01
[백준] 5397번 : 키로거  (0) 2023.09.29
728x90

문제

스택을 직접 구현해서 주어진 명령어에 맞게 실행 결과를 출력하라.

 

접근 방식

스택의 크기는 가변적으로 늘어나야 하기 때문에

Vector 혹은 ArrayList를 사용해서 구현해주면 된다.

 

 

풀이

private static class Stack {
    Vector<Integer> vector = new Vector<>();

    private void push(Integer x) {
        vector.add(x);
    }

    private int pop() {
        try {
            return vector.remove(vector.size() - 1);
        } catch (Exception e) {
            return -1;
        }
    }

    private int size() {
        return vector.size();
    }

    private int empty() {
        return size() == 0 ? 1 : 0;
    }

    private int top() {
        try {
            return vector.get(size() - 1);
        } catch (Exception e) {
            return -1;
        }
    }
}

 

우선 스택 구현 클래스의 코드다.

제네릭 타입으로 지정해줘도 상관 없지만 문제에서는 정수만 사용한다.

 

public static void main(String[] args) throws IOException {
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

    StringBuilder sb = new StringBuilder();

    int n = Integer.parseInt(br.readLine());

    Stack stack = new Stack();

    for (int i = 0; i < n; i++) {
        String[] command = br.readLine().split(" ");

        switch (command[0]) {
            case "push": {
                stack.push(Integer.parseInt(command[1]));
                break;
            }
            case "pop": {
                sb.append(stack.pop()).append("\n");
                break;
            }
            case "size": {
                sb.append(stack.size()).append("\n");
                break;
            }
            case "empty": {
                sb.append(stack.empty()).append("\n");
                break;
            }
            case "top": {
                sb.append(stack.top()).append("\n");
                break;
            }
        }
    }

    bw.write(sb.toString());
    bw.flush();
}

 

위처럼 구현한 스택 클래스를 명령어에 맞게 호출해서 사용한다.

'Java > Algorithms' 카테고리의 다른 글

[백준] 1874번 : 스택 수열  (0) 2023.10.02
[백준] 10773번 : 제로  (0) 2023.10.01
[백준] 1158번 : 요세푸스 문제  (0) 2023.10.01
[백준] 5397번 : 키로거  (0) 2023.09.29
[백준] 1406번 : 에디터  (0) 2023.09.29
728x90

문제

n명의 사람이 원을 그리며 앉아 있을 때 k번째 사람을 한 명씩 빼주는 문제로

리스트를 계속 돌아야 한다.

 

접근 방식

7명의 사람이 원을 그리며 앉아 있을 때

진행 과정은 아래와 같다.

 

1, 2, 3, 4, 5, 6, 7

1, 2, 4, 5, 6, 7

1, 2, 4, 5, 7

1, 4, 5, 7

1, 4, 5

1, 4

4

 

결과는 <3, 6, 2, 7, 5, 1, 4> 라는 순열이 만들어 진다.

 

결국 1부터 n번째 사람이 모두 빠질 때까지 반복문을 돌면서

빠지는 순서대로 출력 버퍼에 추가해주면 된다.

 

문제가 하나 있는데 리스트의 끝까지 왔다면 다시 처음으로 돌아가야 한다.

이터레이터는 전후 한 칸 이동만 가능하기 때문에 처음으로 갈 수가 없다.

 

iterator = list.listIterator();
iterator = list.listIterator(0);

 

이터레이터를 초기화 하면 항상 0번째 인덱스부터 시작하고

특정 인덱스부터 시작하고 싶은 경우에는 해당 인덱스 번호를 파라미터로 주면 된다.

 

풀이

public class Main {

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

		bw.write("<");

		String[] input = br.readLine().split(" ");
		int n = Integer.parseInt(input[0]);
		int k = Integer.parseInt(input[1]);

		LinkedList<Integer> list = new LinkedList<>();

		for (int i = 1; i <= n; i++) {
			list.add(i);
		}

		ListIterator<Integer> iterator = list.listIterator();

		int cur = 0;

		while (!list.isEmpty()) {
			if (list.size() == 1){
				bw.write(list.get(0) + "");
				list.remove(0);
			}
			else {
				for (int i = 0; i < k; i++) {
					if (iterator.hasNext()) {
						cur = iterator.next();
					} else {
						iterator = list.listIterator();
						cur = iterator.next();
					}

					if (i == k - 1 && list.size() > 1) {
						bw.write(cur + ", ");
						iterator.remove();
					}
				}
			}

		}

		bw.write(">");
		bw.flush();
		bw.close();
	}
}

 

자바에서 LinkedList는 Queue의 구현 클래스이기도 해서

나중에 이 문제를 다시 큐를 사용해서 풀어보겠다.

'Java > Algorithms' 카테고리의 다른 글

[백준] 10773번 : 제로  (0) 2023.10.01
[백준] 10828번 : 스택  (0) 2023.10.01
[백준] 5397번 : 키로거  (0) 2023.09.29
[백준] 1406번 : 에디터  (0) 2023.09.29
[백준] 3273번 : 두 수의 합  (0) 2023.09.28
728x90

문제

키보드를 누른 기록이 저장된 키로거 문자열에서

화살표와 백스페이스를 계산해서 실제 비밀번호를 알아내는 문제

 

접근 방식

에디터에서 사용했던 방식처럼 이번에도 연결 리스트와 이터레이터를 사용하면 될거 같다.

 

어떤 부분에 글자가 추가되고 어떤 부분이 빠지는지 수정해서 최종 결과를 구한다.

 

풀이

public static void main(String[] args) throws IOException {
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

    int n = Integer.parseInt(br.readLine());

    for (int i = 0; i < n; i++) {
        char[] testCase = br.readLine().toCharArray();

        LinkedList<Character> list = new LinkedList<>();
        ListIterator<Character> iterator = list.listIterator();

        for (char c : testCase) {
            switch (c) {
                case '-': {
                    if (iterator.hasPrevious()) {
                        iterator.previous();
                        iterator.remove();
                    }
                    break;
                }
                case '<': {
                    if (iterator.hasPrevious()) {
                        iterator.previous();
                    }
                    break;
                }
                case '>': {
                    if (iterator.hasNext()) {
                        iterator.next();
                    }
                    break;
                }
                default: {
                    iterator.add(c);
                    break;
                }
            }
        }

        for (char ch : list) {
            bw.write(ch);
        }
        bw.write("\n");
        bw.flush();
    }
    bw.close();
}

 

'Java > Algorithms' 카테고리의 다른 글

[백준] 10828번 : 스택  (0) 2023.10.01
[백준] 1158번 : 요세푸스 문제  (0) 2023.10.01
[백준] 1406번 : 에디터  (0) 2023.09.29
[백준] 3273번 : 두 수의 합  (0) 2023.09.28
[백준] 1475번 : 방 번호  (0) 2023.09.28
728x90

문제

주어진 명령어에 맞게 텍스트를 수정하는 에디터를 구현하는 문제

 

접근 방식

임의 위치의 요소를 수정해야 하니 배열보다는 연결 리스트를 사용하는 것이 좋을 것 같다.

 

커서의 위치를 기록하여 데이터의 추가/삭제 명령어가 입력 되었을 때

해당 커서의 인덱스를 수정하도록 하면 될거 같다.

 

사실 스택으로도 풀 수 있는 문제지만 연결 리스트에 대해 학습 중이기 때문에

지금은 연결 리스트로 풀고 나중에 다시 스택으로 풀어보겠다.

 

풀이

우선 처음 답안을 제출하고 시간 초과로 실패한 코드를 살펴보겠다.

 

public static void main(String[] args) throws IOException {
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

    String before = br.readLine();
    int m = Integer.parseInt(br.readLine());

    LinkedList<Character> list = new LinkedList<>();

    for (int i = 0; i < before.length(); i++) {
        list.add(before.charAt(i));
    }

    int cur = list.size();

    for (int i = 0; i < m; i++) {
        String[] command = br.readLine().split(" ");

        switch (command[0]) {
            case "P": {
                list.add(cur, command[1].charAt(0));
                cur++;
                break;
            }
            case "L": {
                if (cur > 0) {
                    cur--;
                }
                break;
            }
            case "D": {
                if (cur < list.size()) {
                    cur++;
                }
                break;
            }
            case "B": {
                if (cur != 0) {
                    list.remove(cur);
                    cur = cur > 0 ? cur++ : cur;
                }
                break;
            }
        }
    }

    for (Character c : list) {
        System.out.print(c);
    }
}

 

자료형도 캐릭터로 바꿔보고 다 해봤는데도 왜 시간 초과가 뜨는지 알 수가 없어서

바킹독 선생님의 설명을 다시 보니 중요한 실수를 하고 있단걸 깨달았다.

 

연결 리스트는 분명 임의 위치의 요소를 수정하는 것이 효율적인 자료구조지만

그건 해당 인덱스의 주소를 알고 있는 경우에만 시간 복잡도가 O(1)이라는 것이다.

 

수정하려는 인덱스의 주소를 모르고 있다면

연결 리스트는 항상 처음부터 특정 인덱스의 위치까지 조회하는 O(N)의

시간 복잡도를 가지고 있기 때문이다.

 

그러면 지금 발생한 시간 초과를 해결하기 위해서는

특정 인덱스의 주소를 알고 있으면 된다는 의미다.

 

public static void main(String[] args) throws IOException {
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

    String before = br.readLine();
    int m = Integer.parseInt(br.readLine());

    LinkedList<Character> list = new LinkedList<>();
    ListIterator<Character> iterator = list.listIterator();

    for (char c : before.toCharArray()) {
        iterator.add(c);
    }

    for (int i = 0; i < m; i++) {
        String command = br.readLine();

        switch (command.charAt(0)) {
            case 'P': {
                iterator.add(command.charAt(2));
                break;
            }
            case 'L': {
                if (iterator.hasPrevious()) {
                    iterator.previous();
                }
                break;
            }
            case 'D': {
                if (iterator.hasNext()) {
                    iterator.next();
                }
                break;
            }
            case 'B': {
                if (iterator.hasPrevious()) {
                    iterator.previous();
                    iterator.remove();
                }
                break;
            }
        }
    }

    for (Character c : list) {
        bw.write(c);
    }

    bw.flush();
    bw.close();
}

 

ListIterator를 사용하면 이러한 문제를 해결할 수 있다.

 

자바에서 제공해주는 리스트 컬렉션을 수정하고 반복할 때 효과적인 클래스로

next()와 previous() 메서드를 사용해 양방향 순회가 가능하다.

 

ListIterator를 사용하고도 시간 초과가 났는데

출력도 BufferedWriter를 사용해야 시간 초과가 발생하지 않는다.

'Java > Algorithms' 카테고리의 다른 글

[백준] 1158번 : 요세푸스 문제  (0) 2023.10.01
[백준] 5397번 : 키로거  (0) 2023.09.29
[백준] 3273번 : 두 수의 합  (0) 2023.09.28
[백준] 1475번 : 방 번호  (0) 2023.09.28
[백준] 2577번 : 숫자의 개수  (0) 2023.09.28
728x90

문제

서로 다른 양의 정수로 이루어진 수열에서

둘을 합해 주어진 자연수 X가 될 수 있는 경우의 수를 구하라

 

접근 방식

이전까지 풀어왔던 방식과 동일하게 배열에 각 숫자들이 등장 여부를 기록한 후에

현재 숫자와 합해서 X가 될 수 있는 숫자가 등장 했는지를 확인하고

등장 했다면 카운트를 1씩 증가시켜 준다.

 

배열을 사용할 땐 인덱스의 범위를 신경서야 하기 때문에

각 숫자의 범위를 생각하면서 풀면 쉽게 풀 수 있다.

(1 ≤ number ≤ 1000000, 1 ≤ x ≤ 2000000)

 

풀이

public class Main {

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

		int n = Integer.parseInt(br.readLine());
		String[] numbers = br.readLine().split(" ");
		int x = Integer.parseInt(br.readLine());

		int[] arr = new int[2000001];
		int count = 0;

		for (String number : numbers) {
			int num = Integer.parseInt(number);

			if (x - num >= 1 && arr[x - num] == 1) {
				count++;
			}

			arr[num] = 1;
		}

		System.out.println(count);
	}
}

 

'Java > Algorithms' 카테고리의 다른 글

[백준] 5397번 : 키로거  (0) 2023.09.29
[백준] 1406번 : 에디터  (0) 2023.09.29
[백준] 1475번 : 방 번호  (0) 2023.09.28
[백준] 2577번 : 숫자의 개수  (0) 2023.09.28
[배열] 두 수의 합이 100인 경우  (0) 2023.09.27
728x90

문제

방에 주어진 방 번호에 맞게 번호표를 붙이려할 때 필요한 번호표 세트의 최소값을 구해야 한다.

 

하나의 번호표 세트에는 0부터 9까지 각 하나씩 번호표가 있고

6과 9는 뒤집으면 같은 경우니 같은 숫자라고 취급한다.

 

접근 방식

6과 9를 제외한 다른 값들은 세트 당 하나씩만 포함하니

여러개인 경우 그만큼 세트가 필요함

6과 9는 같은 숫자로 취급하여 2개 당 세트 하나로 처리 가능

 

6과 9를 제외한 각 숫자의 등장 빈도(max)와

6과 9의 등장 빈도를 합한 값(sixAndNine)을 구한다.

 

max * 2가 sixAndNine보다 작으면

필요한 세트의 기준이 6과 9의 등장 빈도가 되고

같거나 작다면 max가 기준이 된다.

 

풀이

public class Main {

	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);

		String roomNumber = scanner.nextInt() + "";

		int[] count = new int[10];
		int max = 0;
		int sixAndNine = 0;
		int result = 0;

		for (int i = 0; i < roomNumber.length(); i++) {
			count[roomNumber.charAt(i) - '0']++;
		}

		for (int i = 0; i < count.length; i++) {
			if (i == 6 || i == 9) {
				continue;
			}
			max = Math.max(max, count[i]);
		}

		sixAndNine = count[6] + count[9];

		if (max * 2 < sixAndNine) {
			result = (int) Math.ceil(sixAndNine / 2.0);
		} else {
			result = max;
		}

		System.out.println(result);
	}
}

'Java > Algorithms' 카테고리의 다른 글

[백준] 1406번 : 에디터  (0) 2023.09.29
[백준] 3273번 : 두 수의 합  (0) 2023.09.28
[백준] 2577번 : 숫자의 개수  (0) 2023.09.28
[배열] 두 수의 합이 100인 경우  (0) 2023.09.27
[백준] 2292번 : 벌집  (0) 2023.07.30
728x90

문제

숫자 a, b, c를 입력 받아 세 수를 모두 곱한 결과에

0부터 9까지의 숫자가 각각 몇 번 등장하는지 출력하는 문제다.

 

접근 방식

이전 글에서 풀어봤던 방식처럼

각 수의 등장 횟수를 저장할 배열을 만들면 된다.

 

계산 결과를 문자열로 만들고 반복문을 돌면서

해당하는 숫자의 인덱스에 1씩 더 해주기만 하면 된다.

 

풀이

public class Main {

	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);

		int a = scanner.nextInt();
		int b = scanner.nextInt();
		int c = scanner.nextInt();

		String result = String.valueOf(a * b * c);

		int[] counts = new int[10];

		for (int i = 0; i < result.length(); i++) {
			int number = result.charAt(i) - '0';

			counts[number]++;
		}

		for (int count : counts) {
			System.out.println(count);
		}
	}
}

'Java > Algorithms' 카테고리의 다른 글

[백준] 3273번 : 두 수의 합  (0) 2023.09.28
[백준] 1475번 : 방 번호  (0) 2023.09.28
[배열] 두 수의 합이 100인 경우  (0) 2023.09.27
[백준] 2292번 : 벌집  (0) 2023.07.30
[백준] 2720번 : 세탁소 사장 동혁  (0) 2023.07.30

+ Recent posts