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

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

+ Recent posts