728x90

29번 수 찾기


내가 떠올린 풀이 해설

N의 최대 범위가 100,000이므로 단순 반복문으로는 풀 수가 없다. 이진 탐색을 적용하면 logn의 시간 복잡도를 사용하므로 이진 탐색을 이용해서 풀어야 된다. 이진 탐색은 정렬이 된 상태여야 하므로 정렬을 하고 start = 0 end = arr.length - 1로 기준을 잡는다. midV에 중앙값을 넣는다. 만약 midV가 크면 end의 값을 mid - 1로 바꿔준다. 작으면 start값을 mid + 1의 값으로 바꿔준다. 같으면 find를 true로 넣어준 후 break로 빠져나온다.


정확한 풀이

import java.io.*;
import java.util.*;
public class Baek1920 {

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		int n = Integer.parseInt(br.readLine());
		int []arr = new int[n]; 
		StringTokenizer st = new StringTokenizer(br.readLine());
		for(int i = 0; i < n; i++) {
			arr[i] = Integer.parseInt(st.nextToken());
		}
		Arrays.sort(arr);
		int m = Integer.parseInt(br.readLine());
		st = new StringTokenizer(br.readLine());
		
		for(int i = 0; i < m; i++) {
			int target = Integer.parseInt(st.nextToken());
			boolean result = false;
			int start = 0;
			int end = arr.length - 1;
			while(start <= end) {
				int mid = (start + end) / 2;
				int midV = arr[mid];
				if(midV > target) {
					end = mid - 1;
				}
				else if(midV < target) {
					start = mid + 1;
				}
				else {
					result = true;
					break;
				}
			}
			if(result) {
				System.out.println(1);
			}
			else {
				System.out.println(0);
			}
		}
	}
}

30번 문제 기타 레슨


내가 떠올린 풀이 해설

문제를 이해하는데 시간이 걸렸다. 블루레이 크기가 모두 같고 녹화 순서가 바뀌지 않아야 함이라는 조건에서 이진 탐색을 사용해야된다는 단서이다. 첫 레슨부터 마지막까지 차례대로 저장하다 보면 지정한 크기로 모든 레슨을 저장할 수 있는지 판단할 수 있기 때문이다.

모두 저장할 수 있으면 크기를 줄이고 저장할 수 없다면 크키를 늘려주는 방식으로 크기의 최솟값을 알 수 있다.


정확한 풀이

import java.io.*;
import java.util.*;
public class Baek2343 {

	public static void main(String[] args) throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		
		int n = Integer.parseInt(st.nextToken());
		int m = Integer.parseInt(st.nextToken());
		
		int []arr = new int[n];
		int start = 0;
		int end = 0;
		st = new StringTokenizer(br.readLine());
		for(int i = 0; i < n; i++) {
			arr[i] = Integer.parseInt(st.nextToken());
			if(start < arr[i]) {
				start = arr[i];  // 레슨 최댓값을 시작 인덱스로 저장하기
			}
			end = end + arr[i]; // 모든 래슨의 총합을 종료 인덱스로 저장하기
		}
		while(start <= end) {
			int mid = (start + end) / 2;
			int sum = 0;
			int count = 0;
			for(int i = 0; i < n; i++) {  // mid 값으로 모든 레슨을 저장할 수 있는지 확인
				if(sum + arr[i] > mid) {
					count++;
					sum = 0;
				}
				sum = sum + arr[i];
			}
			if(sum != 0) {  // 탐색후 sum이 0이 아니면 블루레이가 1개 더 필요하므로 더함
				count++;
			}
			if(count > m) {
				start = mid + 1;
			}
			else {
				end = mid - 1;
			}
		}
		System.out.println(start);
	}
}

 


31번 문제 K번째 수


책 풀이 해설

k의 범위가 1 ~ min(10^9, N^2)이므로 시간 복잡도가 N^2인 알고리즘은 사용할 수 없다. 이진 탐색으로 중앙값보다 작은 수의 개수를 세면서 범위를 절반씩 줄이는 방법으로 B [k] 값을 구한다. 작은 수의 개수가 k - 1 개인 중앙값이 정답이다.


정확한 풀이

import java.util.*;
public class Baek1300 {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int m = sc.nextInt();
		
		long start = 1;
		long end = m;
		long answer = 0;
		
		while(start <= end) {
			long mid = (start + end) / 2;
			long cnt = 0;
			
			for(int i = 1; i <= n; i++) {
				cnt += Math.min(mid / i, n);
			}
			if(cnt < m) {
				start = mid + 1;
			}
			else {
				answer = mid;
				end = mid - 1;
			}
		}
		System.out.println(answer);
	}
}

문제점

이진탐색을 떠올리기 힘들었고 중앙값보다 작은 수의 개수를 세면서 줄이는 방법을 이용해서 작은 수의 개수가 k -1 개인 중앙값이 정답이라는 아이디어를 못 떠올렸다.


백준 11866번 요세푸스 문제 0

내가 떠올린 풀이 해설

기본 큐를 이용해서 푸는 문제이다. 큐가 비어 있을 때까지 반복한다. 큐를 pop 하고 다시 그 수를 push 해서 k번째 pop을 할 때 String str에 더해준다. 


정확한 풀이

import java.io.*;
import java.util.*;
public class Baek11866 {

	public static void main(String[] args) throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		
		int n = Integer.parseInt(st.nextToken());
		int m = Integer.parseInt(st.nextToken());
		
		Queue<Integer> que = new LinkedList<>();
		
		for(int i = 1; i <= n; i++) {
			que.offer(i);
		}
		int cnt = 0;
		String str = "<";
		while(!que.isEmpty()) {
			cnt++;
			if(cnt == m) {
				str += que.poll() + ", ";
				cnt = 0;
			}
			else {
				que.offer(que.poll());
			}
		}
		str = str.substring(0, str.length() - 2);
		System.out.print(str + ">");
	}
}

오늘의 회고

오늘은 이진탐색 문제를 풀었습니다. 이진 탐색을 사용하는 문제에서 이진 탐색을 사용해야 되는 아이디어를 떠올리기 힘들었습니다. 마지막 문제는 어려워서 풀지 못했습니다. 이진 탐색에 대해 공부하기 위해 내일은 이진 탐색 중에 난의도가 높지 않은 문제를 풀겠습니다.

 

728x90
728x90

백준 10773번 제로


내가 떠올린 풀이 해설

기본 스택 문제이다. 스택을 이용해서 0이 아니면 스택에 push 하고 0이면 pop을 해서 스택에 남아있는 수를 sum 해주면 된다.


정확한 풀이

import java.io.*;
import java.util.*;
public class Baek10773 {

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int n = Integer.parseInt(br.readLine());
		
		Stack<Integer> stack = new Stack<>();
		
		for(int i = 0; i < n; i++) {
			int m = Integer.parseInt(br.readLine());
			if(m != 0) {
				stack.push(m);
			}
			else {
				stack.pop();
			}
		}
		int sum = 0;
		for(int i = 0; i < stack.size(); i++) {
			sum += stack.get(i);
		}
		System.out.println(sum);
	}
}

백준 1259번 팰린드롬수


내가 떠올린 풀이 해설

기본 문자열 문제 입니다. while을 true로 설정하고 0이면 break을 하고 0이 아니면 stringbulider에서 reverse를 이용해서 뒤집고 그전에 문자랑 같으면 yes 다르면 no를 출력한다.


import java.io.*;
import java.util.*;
public class Baek1259 {

	public static void main(String[] args) throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		while(true) {
			String n = br.readLine();
			if(n.equals("0")) {
				break;
			}
			else {
				String st = new StringBuilder(n).reverse().toString();
				if(st.equals(n)) {
					System.out.println("yes");
				}
				else {
					System.out.println("no");
				}
			}
		}
	}
}

오늘의 회고

오늘은 한주를 시작하는 월요일이라 기본 개념을 물어보는 알고리즘 2문제를 풀었습니다. 주말에 재밌게 놀았으니 평일에 다시 마음 다잡고 이번주도 열심히 나아가겠습니다.

728x90

'알고리즘 > 알고리즘 문제풀이' 카테고리의 다른 글

백준) 이분탐색  (0) 2022.06.01
Do it! 알고리즘 코딩 테스트 (29번 ~ 31번)  (0) 2022.05.31
백준)정렬  (0) 2022.05.27
Do it! 알고리즘 코딩 테스트 (26번 ~ 28번)  (0) 2022.05.26
백준)DFS  (0) 2022.05.25
728x90

백준 10814번 나이순 정렬


내가 떠올린 풀이 해설

정렬 문제이다. Arrays.sort()를 사용해서 정렬을 한다. 또한 Comparator를 이용한다. o1은 첫 번째 행이고 arr [0][0]이다.  o2는 두 번째 행이고 arr [1][0]이다. o1[0] - o2[0] 정렬해준다.


정확한 풀이

import java.io.*;
import java.util.*;
public class Baek10814 {

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		int n = Integer.parseInt(br.readLine());
		String [][] arr = new String[n][2];
		
		for(int i = 0; i < n; i++) {
			StringTokenizer st = new StringTokenizer(br.readLine());
			arr[i][0] = st.nextToken();
			arr[i][1] = st.nextToken();
		}
		Arrays.sort(arr, new Comparator<String[]>() {

			@Override
			public int compare(String[] o1, String[] o2) {
				return Integer.parseInt(o1[0]) - Integer.parseInt(o2[0]);
			}
			
		});
		for(int i = 0; i < n; i++) {
			System.out.println(arr[i][0]);
			System.out.println(arr[i][1]);
		}
	}
}

백준 11650번 좌표 정렬하기


내가 떠올린 풀이 해설

기본 정렬 문제이다. Point 클래스를 만들어서 Comparable를 이용해서 정렬을 진행했다. this.x 와 o.x가 같으면 y값으로 비교했다.

import java.io.*;
import java.util.*;
public class Baek11650 {

	public static void main(String[] args) throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		int n = Integer.parseInt(br.readLine());
		ArrayList<Point> arr = new ArrayList<>();
		
		for(int i = 0; i < n; i++) {
			StringTokenizer st = new StringTokenizer(br.readLine());
			int x = Integer.parseInt(st.nextToken());
			int y = Integer.parseInt(st.nextToken());
			arr.add(new Point(x, y));
		}
		Collections.sort(arr);
		for(Point o : arr) {
			System.out.println(o.x + " " + o.y);
		}
	}
}
class Point implements Comparable<Point> {
	int x;
	int y;
	Point(int x, int y) {
		this.x = x;
		this.y = y;
	}
	@Override
	public int compareTo(Point o) {
		if(this.x == o.x) {
			return this.y - o.y;
		}
		else {
			return this.x - o.x;
		}
	}
}

오늘의 회고

복습을 끝내고 시간이 남아서 정렬 문제 2문제를 풀었습니다. 기본적인 정렬 문제라 시간이 많이 걸리지는 않았습니다. 아직 배워야 하는 알고리즘들이 많은데 너무 성급하게 넘어가지 말고 정석대로 공부하자.

728x90
728x90

26번 DFS와 BFS


내가 떠올린 풀이 해설

DFS와 BFS를 구현할 수 있는지 물어보는 기본 문제이다.

문제 조건에서 작은 번호의 노드부터 탐색한다고 했으므로 인접 노드를 오름차순으로 정렬한 후 구현한다. 또한 DFS가 끝났을 떼 방문 배열을 초기화해준다.


정확한 풀이

import java.io.*;
import java.util.*;
public class Baek1260 {
	static ArrayList<Integer> arr[];
	static boolean visited[];
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		
		int n = Integer.parseInt(st.nextToken());
		int m = Integer.parseInt(st.nextToken());
		int v = Integer.parseInt(st.nextToken());
		
		arr = new ArrayList[n + 1];
		for(int i = 1; i <= n; i++) {
			arr[i] = new ArrayList<>();
		}
		
		for(int i = 0; i < m; i++) {
			st = new StringTokenizer(br.readLine());
			int e = Integer.parseInt(st.nextToken());
			int s = Integer.parseInt(st.nextToken());
			arr[e].add(s);
			arr[s].add(e);
		}
		for(int i = 1; i <= n; i++) {
			Collections.sort(arr[i]);
		}
		visited = new boolean[n + 1];
		DFS(v);
		System.out.println();
		visited = new boolean[n + 1];
		BFS(v);
	}
	private static void BFS(int i) {
		Queue<Integer> que = new LinkedList<>();
		que.add(i);
		visited[i] = true;
		
		while(!que.isEmpty()) {
			int now = que.poll();
			System.out.print(now + " ");
			for(int b : arr[now]) {
				if(!visited[b]) {
					visited[b] = true;
					que.add(b);
				}
			}
		}
	}
	private static void DFS(int i) {
		System.out.print(i + " ");
		visited[i] = true;
		for(int b : arr[i]) {
			if(!visited[b]) {
				DFS(b);
			}
		}
	}
}

27번 미로 탐색


내가 떠올린 풀이 해설

N, M의 최대 크기가 100으로 매우 작기 때문에 DFS나 BFS의 시간제한은 생각하지 않아도 되는 문제다.

지나야 하는 칸수의 최솟값을 구하는 문제이므로 BFS로 풀었다. 상하좌우를 탐색하면서 칸의 숫자가 1이면서 아직 방문하지 않았다면 큐에 삽입한다.


정확한 풀이

import java.io.*;
import java.util.*;
public class Baek2178 {
	static int arr[][];
	static boolean visited[][];
	static int []dx = {1, 0, -1, 0};
	static int []dy = {0, 1, 0, -1};
	static int n,m;
	public static void main(String[] args) throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		
		n = Integer.parseInt(st.nextToken());
		m = Integer.parseInt(st.nextToken());
		
		arr = new int[n][m];
		visited = new boolean[n][m];
		
		for(int i = 0; i < n; i++) {
			st = new StringTokenizer(br.readLine());
			String line = st.nextToken();
			for(int j = 0; j < m; j++) {
				arr[i][j] = Integer.parseInt(line.substring(j, j + 1));
			}
		}
		BFS(0,0);
		System.out.println(arr[n - 1][m - 1]);
	}

	private static void BFS(int i, int j) {
		Queue<int[]> que = new LinkedList<>();
		que.offer(new int[]{i, j});
		visited[i][j] = true;
		while(!que.isEmpty()) {
			int now[] = que.poll();
			
			for(int k = 0; k < 4; k++) {
				int x = now[0] + dx[k];
				int y = now[1] + dy[k];
				if(x >= 0 && x < n && y >= 0 && y < m) {
					if(arr[x][y] != 0 && !visited[x][y]) {
						visited[x][y] = true;
						arr[x][y] = arr[now[0]][now[1]] + 1;
						que.add(new int[] {x,y});
					}
				}
			}
		}
	}
}

문제점

자연스럽게 Integer.parseInt(st.nextToken())으로 코드를 작성했는데 오류가 발생했다. 왜 오류가 났는지 찾다가 입력 예제가 띄어쓰기로 되어있는 게 아니라 한 줄로 붙어었다는것을 발견했다... que.add 할 때 {x, y}를 add 해야 되는데 {i, j}를 add를 해서 계속 답이 안 나왔다. 이번 문제 오류를 찾느라 한참 걸렸다.


28번 문제 트리의 지름


정확한 풀이

import java.io.*;
import java.util.*;
public class Baek1167 {
	static boolean visited[];
	static int[] distance;
	static ArrayList<Edge> []arr;
	public static void main(String[] args) throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int n = Integer.parseInt(br.readLine());
		
		arr = new ArrayList[n + 1];
		for(int i = 1; i <= n; i++) {
			arr[i] = new ArrayList<Edge>();
		}
		for(int i = 0; i < n; i++) {
			StringTokenizer st = new StringTokenizer(br.readLine());
			int s = Integer.parseInt(st.nextToken());
			while(true) {
				int e = Integer.parseInt(st.nextToken());
				if(e == -1) {
					break;
				}
				int v = Integer.parseInt(st.nextToken());
				arr[s].add(new Edge(e, v));
			}
		}
		distance = new int[n + 1];
		visited = new boolean[n + 1];
		BFS(1);
		int max = 1;
		for(int i = 2; i <= n; i++) {
			if(distance[max] < distance[i]) {
				max = i;
			}
		}
		distance = new int[n + 1];
		visited = new boolean[n + 1];
		BFS(max);
		Arrays.sort(distance);
		System.out.println(distance[n]);
	}
	private static void BFS(int index) {
		Queue<Integer> que = new LinkedList<>();
		que.add(index);
		visited[index] = true;
		while(!que.isEmpty()) {
			int now = que.poll();
			for(Edge i : arr[now]) {
				int e = i.e;
				int v = i.value;
				if(!visited[e]) {
					visited[e] = true;
					que.add(e);
					distance[e] = distance[now] + v;
				}
			}
		}	
	}
}
class Edge {
	int e;
	int value;
	public Edge(int e, int value) {
		this.e = e;
		this.value = value;
	}
}

문제점

문제를 고민해봤지만 풀지 못했다. 아직 골드까지 풀기는 부족한 실력인 것 같다.

 

오늘의 회고

오늘은 책에 있는 문제를 풀었습니다. 책이 실전 대비 책이라 그런지 어려운 문제들이 포함되어있습니다.ㅠㅠ  안 풀린다고 좌절하지 말고 천천히 기본부터 익혀 나가겠습니다. 내일은 그동안 학습했던 문제들 복습하고 정리하는 시간과 시간이 되면 오늘 보단 쉬운 문제를 풀겠습니다.

728x90

'알고리즘 > 알고리즘 문제풀이' 카테고리의 다른 글

백준) 스택, 문자열  (0) 2022.05.30
백준)정렬  (0) 2022.05.27
백준)DFS  (0) 2022.05.25
Do it! 알고리즘 코딩 테스트 (22번 ~ 25번)  (0) 2022.05.24
Do it! 알고리즘 코딩테스트(16번 ~ 20번)  (0) 2022.05.23
728x90

백준 2606번 바이러스


내가 떠올린 풀이 해설

어제 풀었던 연결 요소의 개수 문제를 응용해서 풀면 된다. 어제 문제는 DFS 총 수행 횟수를 구하는 문제였지만 오늘 하나의 기준점에서 DFS가 몇 번 수행되는지 count를 구하는 문제이다.


정확한 풀이

import java.io.*;
import java.util.*;
public class Baek2606 {
	static ArrayList<Integer> arr[];
	static boolean visited[];
	static int cnt, v;
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		int n = Integer.parseInt(br.readLine());
		int m = Integer.parseInt(br.readLine());
		
		arr = new ArrayList[n + 1];
		visited = new boolean[n + 1];
		
		for(int i = 1; i <=n; i++) {     // 인덱스 편의상 n+1설정, 0번째 요소는 사용 X  
			arr[i] = new ArrayList<>();
		}
		v = 1; // 탐색 시장할 정점의 번호
		for(int i = 0; i < m; i++) {
			StringTokenizer st = new StringTokenizer(br.readLine());
			int e = Integer.parseInt(st.nextToken());
			int v = Integer.parseInt(st.nextToken());
			arr[e].add(v);
			arr[v].add(e);
		}
		System.out.println(DFS(v));
	}
	private static int DFS(int i) {
		visited[i] = true;
		for(int b : arr[i]) {
			if(visited[b] == false) {
				cnt++;
				DFS(b);
			}
		}
		return cnt;
	}
}

오늘의 회고

오늘은 늦잠을 자고 게으름이 발동해서 점심 먹고 스터디 카페에 도착해서 DFS 한문제 밖에 풀지 못했습니다. 정신 차리고 내일 DFS문제를 더 풀겠습니다.

728x90
728x90

22번 문제 수 정렬하기 3


잘못된 풀이

import java.io.*;
import java.util.*;
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());
		
		LinkedList<Integer> list = new LinkedList<>();
		StringBuffer bf = new StringBuffer();
		for(int i = 0; i < n; i++) {
			list.add(Integer.parseInt(br.readLine()));
		}
		Collections.sort(list);
		for(int i = 0; i < n; i++) {
			bf.append(list.get(i));
		}
		System.out.println(bf.toString());
	}

}

내가 떠올린 풀이 해설

LinkedList로 받아 Collections.sort로 정렬하려고 했는데 메모리 초과가 발생했다.


정확한 풀이

import java.io.*;
import java.util.*;
public class Baek10989 {

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		int[] cnt = new int [10001];
		
		
		int n = Integer.parseInt(br.readLine());
		
		StringBuffer bf = new StringBuffer();
		
		for(int i = 0; i < n; i++) {
			cnt[Integer.parseInt(br.readLine())]++;
		}
		br.close();
		
		for(int i = 1; i < 10001; i++) {
			while(cnt[i] > 0) {
				bf.append(i + "\\n");
				cnt[i]--;
			}
			
		}
		System.out.println(bf.toString());
	}
}

문제점

sort 를 사용하지 않고 카운팅 정렬을 사용하는 방법이다. 시간 복잡도는 O(N + K)이다. K는 자릿수를 의미하는데 입력 데이터가 K 보다 훨씬 큰 경우. 즉 데이터가 많으면 많을수록O(N)에 가깝기 때문에 이상적으로는 O(N)이라고 보아도 무방하다. 

참고 블로그 : https://st-lab.tistory.com/107

 

[백준] 10989번 : 수 정렬하기 3 - JAVA [자바]

www.acmicpc.net/problem/10989 10989번: 수 정렬하기 3 첫째 줄에 수의 개수 N(1 ≤ N ≤ 10,000,000)이 주어진다. 둘째 줄부터 N개의 줄에는 숫자가 주어진다. 이 수는 10,000보다 작거나 같은 자연수이다. ww..

st-lab.tistory.com


23번 문제 연결 요소의 개수


내가 떠올린 풀이 해설

노드의 최대 개수가 1,000이므로 시간 복잡도는 N^2 이하의 알고리즘을 모두 사용할 수 앗다. 그래프를 인접 리스트로 저장하고 방문 배열도 초기화한다. 방향이 없는 그래프 이므로 양쪽 방향으로 에지를 모두 저장 방문하지 않은 노드가 있는지 확인 후 시작점을 다시 탐색한다.

만약 그래프가 모두 연결되었었다면 DFS는 1번 실행된다.


정확한 풀이

import java.io.*;
import java.util.*;

public class Baek11724 {
	static ArrayList<Integer> arr[];
	static boolean visited[];
	
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		
		int n = Integer.parseInt(st.nextToken());
		int m = Integer.parseInt(st.nextToken());
		
		arr = new ArrayList[n + 1];
		visited = new boolean[n + 1];
		for(int i = 1; i < n + 1; i++) {
			arr[i] = new ArrayList<>();
		}
		
		for(int i = 0; i < m; i++) {
			st = new StringTokenizer(br.readLine());
			int e = Integer.parseInt(st.nextToken());
			int v = Integer.parseInt(st.nextToken());
			arr[e].add(v);
			arr[v].add(e);
		}
		int cnt = 0;
		for(int i = 1; i < n + 1; i++) {
			if(!visited[i]) {
				cnt++;
				DFS(i);
			}
		}
		System.out.println(cnt);
	}

	private static void DFS(int i) {
		if(visited[i]) {
			return;
		}
		visited[i] = true;
		for(int b : arr[i])
		if(visited[b] == false) {
			DFS(b);
		}
	}	
}

24번 문제 신기한 소수 찾기

 


내가 떠올린 풀이 해설

DFS는 재귀 함수의 형태를 띠고 있다. 자릿수가 두 개인 현재 수 * 10 + a를 계산해 이 수가 소수인지 판단하여 이 수가 소수인지 판단하고 소수라면 재귀 함수로 함수 자릿수를 하나 늘린다. a가 짝수인 경우는 항상 2를 약수로 가지므로 a가 짝수인 경우를 제외한다.


정확한 풀이

import java.util.*;
public class Baek2023 {
	static int n;
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		
		n = sc.nextInt();
		
		DFS(2,1);
		DFS(3,1);
		DFS(5,1);
		DFS(7,1);
	}

	private static void DFS(int number, int jarisu) {
		if(jarisu == n) {
			if(isPrime(number)) {
				System.out.println(number);
			}
			return;
		}
		for(int i = 1; i < 10; i++) {
			if(i % 2 == 0) {
				continue;
			}
			if(isPrime(number * 10 + i)) {
				DFS(number * 10 + i, jarisu + i);
			}
		}
	}
	

	private static boolean isPrime(int num) {
		for(int i = 2; i <= num /2; i++) {
			if(num % 2 == 0) {
				return false;
			}
		}
		return true;
	}
}

25번 문제 친구 관계 파악하기


내가 떠올린 풀이 해설

N의 최대 범위가 2,000이므로 알고리즘의 시간 복잡도를 고려할 때 자유롭다. 주어진 모든 노드에 DFS를 수행하고 재귀의 깊이가 5 이상이면 1 아니라면 0을 출력한다. DFS의 시간 복잡도는 O(V+E)이므로 최대 4,000 모든 노드를 진행했을 때 4000 * 2000이다.


정확한 풀이

package DoitCodingTest;
import java.io.*;
import java.util.*;
public class Baek13023 {
	static ArrayList<Integer> arr [];
	static boolean visited[];
	static boolean arrive;
	
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		int n = Integer.parseInt(st.nextToken());
		int m = Integer.parseInt(st.nextToken());
		arrive = false;
		
		arr = new ArrayList[n];
		visited = new boolean[n];
		for(int i = 0; i < n; i++) {
			arr[i] = new ArrayList<>();
		}
		for(int i = 0; i < m; i++) {
			st = new StringTokenizer(br.readLine());
			int e = Integer.parseInt(st.nextToken());
			int v = Integer.parseInt(st.nextToken());
			arr[e].add(v);
			arr[v].add(e);
			
		}
		for(int i = 0; i < n; i++) {
			DFS(i, 1);
			if(arrive) {
				break;
			}
		}
		if(arrive) {
			System.out.println(1);
		}
		else {
			System.out.println(0);
		}
	}

	private static void DFS(int now, int depth) {
		if(depth == 5 || arrive) {
			arrive = true;
			return;
		}
		visited[now] = true;
		for(int i : arr[now]) {
			if(!visited[i]) {
				DFS(i, depth + 1);
			}	
		}
		visited[now] = false;
	}
}

오늘의 회고

오늘은 정렬 한 문제와 DFS 문제를 풀어 보았는데 DFS의 개념이 아직 많이 부족한 것 같습니다, 내일은 쉬운 문제에 속하는 DFS문제를 풀어 보겠습니다. 카페에서 공부하다가 오늘부터 스터디 카페로 자리를 옮겼는데 열심히 공부하겠습니다! 

728x90
728x90

16번 문제 버블 소트


잘못된 풀이

import java.io.*;
import java.util.*;

public class Baek1377 {

	public static void main(String[] args) throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int n = Integer.parseInt(br.readLine());
		
		int [] arr = new int[n +1];
		for(int i = 1; i <= n; i++) {
			arr[i] = Integer.parseInt(br.readLine());
		}
		boolean change = false;
		
		for(int i = 1; i <= n + 1; i++) {
			change = false;
			for(int j = 1; j <= n - i; j++) {
				if(arr[j] > arr[j + 1]) {
					change = true;
					int swap = arr[j];
					arr[j] = arr[j + 1];
					arr[j + 1] = swap;
				}
			}
			if(change == false) {
				System.out.println(i);
				break;
			}
		}
		
	}

}

내가 떠올린 풀이 해설

C++ 예시로 보여준 코드를 그대로 적용해서 풀었습니다.


정확한 풀이

import java.io.*;
import java.util.*;

public class Baek1377 {

	public static void main(String[] args) throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int n = Integer.parseInt(br.readLine());
		Sort [] arr = new Sort[n];
		for(int i = 0; i < n; i++) {
			arr[i] = new Sort(Integer.parseInt(br.readLine()), i);
		}
		Arrays.sort(arr);
		int max = 0;
		for(int i = 0; i < n; i++) {
			if(max < arr[i].index - i) {
				max = arr[i].index - i;
			}
		}
		System.out.println(max + 1);
	}
}

class Sort implements Comparable<Sort> {
	int value;
	int index;
	public Sort(int value, int index) {
		this.value = value;
		this.index = index;
	}
	@Override
	public int compareTo(Sort o) {
		return this.value - o.value;
	}
}

문제점

이 문제는 N의 최대 범위가 500,000이므로 버블 정렬로 문제를 풀면 시간 초과가 나온다. 각 데이터마다 정렬 전 index값에서 정렬 후 index값을 빼고 최댓값을 찾는다. 그리고 swap이 일어나지 않은 반복문이 한번 더 실행되는 것을 감안해 max에 + 1을 해준다.


17번 문제 소트 인사이드


내가 떠올린 풀이 해설

N의 크기가 1,000,000,000 보다 작거나 같은 자연수이다. 자연수를 받아 자릿수 별로 정렬하는 문제이므로 숫자를 String으로 받은 후 정렬을 List에 Arrays.stream(arr).boxed().collect(Collectors.toList()); 로 담아 Collections.sort(integer, Comparator.reverseOrder()); 를 이용해 내림차순 정렬을 진행했다.


정확한 풀이

import java.util.*;
import java.util.stream.Collectors;
public class Baek1427 {

	public static void main(String[] args) throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String str = br.readLine();
		
		int []arr = new int[str.length()];
		for(int i = 0; i < str.length(); i++) {
			arr[i] = str.charAt(i) - 48;
		}
		List<Integer> integer = Arrays.stream(arr).boxed().collect(Collectors.toList());
		Collections.sort(integer, Comparator.reverseOrder());
		
		for(int i = 0; i < str.length(); i++) {
			System.out.print(integer.get(i));
		}
		
	}

}

18번 문제 ATM


내가 떠올린 풀이 해설

N의 최댓값이 1,000이고 시간제한이 1초이므로 시간 복잡도가 O(n^2) 이하인 정렬 알고리즘 아무거나 사용해도 된다.

Arrays.sort로 정렬을 하고 인출 시간을 sum에 더하고 total 걸린 시간을 구하기 위해 sum을 다시 total에 더했다.


정확한 풀이

import java.io.*;
import java.util.*;
public class Baek11399 {

	public static void main(String[] args) throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		int n = Integer.parseInt(br.readLine());
		int []arr = new int[n];
		StringTokenizer st = new StringTokenizer(br.readLine());
		for(int i = 0; i < n; i++) {
			arr[i] = Integer.parseInt(st.nextToken());
		}
		Arrays.sort(arr);
		int sum = 0;
		int total = 0;
		for(int i = 0; i < n; i++) {
			sum += arr[i];
			total += sum;
		}
		System.out.println(total);
	}

}

19번 문제 K번째 수


내가 떠올린 풀이 해설

N의 최대 범위가 5,000,000이므로 O(nlogn)의 시간 복잡도로 정렬을 해야 된다. 간단하게 Arrays.sort로 풀었다.


정확한 풀이

import java.io.*;
import java.util.*;

public class Baek11004 {

	public static void main(String[] args) throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		int n = Integer.parseInt(st.nextToken());
		int m = Integer.parseInt(st.nextToken());
		
		int[] arr = new int[n];
		st = new StringTokenizer(br.readLine());
		for(int i = 0; i < n; i++) {
			arr[i] = Integer.parseInt(st.nextToken());
		}
		Arrays.sort(arr);
		System.out.println(arr[m - 1]);
	}

}

20번 문제 수 정렬하기 2


내가 떠올린 풀이 해설

N의 최대 범위가 1,000,000이므로 O(nlogn)의 시간 복잡도로 정렬을 수행해야 된다. Collections.sort을 이용해서 해결했다.


정확한 풀이

import java.io.*;
import java.util.*;
public class Baek2751 {

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringBuffer bf = new StringBuffer();
		int n = Integer.parseInt(br.readLine());
		int [] arr = new int[n];
		ArrayList<Integer> list = new ArrayList<>();
		for(int i = 0; i < n; i++) {
			list.add(Integer.parseInt(br.readLine()));
			
		}
		Collections.sort(list);
		for(int i = 0; i < n; i++) {
			bf.append(list.get(i) + "\\n");
		}
		System.out.println(bf.toString());
	}

}

문제점

Arrays.sort 로 쓰면 시간 초과가 난다. Arrays.sort() 의 경우 dual-pivot Quicksort 알고리즘을 사용한다. 물론 평균 시간 복잡도가O(nlogn) 이고 매우 빠른 알고리즘이다. 그러나 최악의 경우 시간 복잡도는O(n2) 이다. Collections.sort() 은 Timsort이다. Timsort 의 경우 합병 및 삽입 정렬 알고리즘을 사용한다. 두 가지가 섞여있는 정렬 알고리즘을 hybrid sorting algorithm이라고 하는데, 합병 정렬은 최선, 최악 모두 O(nlogn)을 보장하고 삽입 정렬은 최선의 경우는 O(n) , 최악의 경우는 O(n2)이다. 그리고 두 정렬 모두 안정 정렬이기 때문에 Timsort를 hybrid stable sorting algorithm이라고도 한다. 즉, 합병 정렬의 최악의 경우와 삽입 정렬의 최선의 경우를 짬뽕한 알고리즘이 Timsort라는 것이다. 

-참고 블로그 : https://st-lab.tistory.com/106

 

[백준] 2751번 : 수 정렬하기 2 - JAVA [자바]

www.acmicpc.net/problem/2751 2751번: 수 정렬하기 2 첫째 줄에 수의 개수 N(1 ≤ N ≤ 1,000,000)이 주어진다. 둘째 줄부터 N개의 줄에는 숫자가 주어진다. 이 수는 절댓값이 1,000,000보다 작거나 같은 정수이..

st-lab.tistory.com

 

오늘의 회고

오늘은 Do it 알고리즘 책에 있는 문제를 풀었습니다. 정렬에 관한 기본적인 문제 5문제를 풀었고 그동안 문제를 풀면서 Arrays.sort, Collections.sort를 많이 사용하였는데 시간 복잡도와 어떤 정렬을 사용하는지 모르고 사용하였습니다. sort에 대해 오늘 정렬 문제를 풀면서 학습하게 되었습니다. 정렬에 관한 알고리즘을 공부하고 시간 복잡도를 고려에 적절한 알고리즘을 사용해야 될 것 같습니다. 

728x90

'알고리즘 > 알고리즘 문제풀이' 카테고리의 다른 글

백준)DFS  (0) 2022.05.25
Do it! 알고리즘 코딩 테스트 (22번 ~ 25번)  (0) 2022.05.24
백준) 수학, 좌표정렬  (0) 2022.05.21
Do it! 알고리즘 코딩테스트(14번)  (0) 2022.05.20
백준) 스택, 덱, 큐  (0) 2022.05.19
728x90

백준 1085번 직사각형에서 탈출


내가 생각한 풀이

기준점 (0, 0)에서 끝점 (w, h)까지의 직사각형이 생기는데 기준점과 끝면으로 생긴 직사각형 면에 가장 가까운 거리를 구하는 문제이다. 저는 x의 좌표에서 기준점을 빼고 w좌표에서 x를 빼주고 Math.min을 이용해서 최솟값을 저장하고 y도 같은 방법으로 최솟값을 저장하고 두개의 최솟값을 다시 Math.min으로 최솟값을 구해서 출력해준다.


정확한 풀이

import java.util.*;
import java.io.*;

public class Baek1085 {

	public static void main(String[] args) throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		int x = Integer.parseInt(st.nextToken());
		int y = Integer.parseInt(st.nextToken());
		int w = Integer.parseInt(st.nextToken());
		int h = Integer.parseInt(st.nextToken());
		
		int endX = w - x;
		int endY = h - y;
		
		int m = Math.min(x, y);
		int n = Math.min(endX, endY);
		
		int answer = Math.min(m, n);
		System.out.println(answer);
	}

}

백준 1181번 단어 정렬


내가 생각한 풀이

String 배열로 문자열을 받아서 Comparator를 이용해서 단어 길이가 같을 경우 return o1.compareTo(o2);를 해주고 길이가 다르면 길이 순으로 정렬을 한다. 같은 단어가 있을 때 for문으로 탐색 후 그 전의 단어와 같을 경우 하나만 출력을 해줘서 중복을 방지한다.


정확한 풀이

import java.io.*;
import java.util.*;

public class Baek1181 {

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int n = Integer.parseInt(br.readLine());
		
		String []str = new String[n];
		
		
		for(int i = 0; i < n; i++) {
			str[i] = br.readLine();
		}		
		Arrays.sort(str, new Comparator<String>() {
			@Override
			public int compare(String o1, String o2) {
				if(o1.length() == o2.length()) {
					return o1.compareTo(o2);
				}
				else {
					return o1.length() - o2.length();
				}
			}
		});
		System.out.println(str[0]);
		for(int i = 1; i < n; i++) {
			if(!str[i].equals(str[i - 1])) {
				System.out.println(str[i]);
			}
		}
	}
}

 


오늘의 회고

오늘은 어제 못풀었던 정렬에 관한 쉬운 문제 2문제를 풀어봤습니다. 정렬의 comparator를 이용하는 문제에서 아직은 완벽하게 구현하기 부족한 점이 있고 복습을 하면서 완전하게 내것으로 만들어야 될 것 같습니다. 아직 갈 길이 멀지만 급하게 하지 않고 천천히 꾸준하게 준비하겠습니다. 

728x90

+ Recent posts