알고리즘 종류 : 이진 탐색

문제

숫자 카드는 정수 하나가 적혀져 있는 카드이다. 상근이는 숫자 카드 N개를 가지고 있다. 정수 M개가 주어졌을 때, 이 수가 적혀있는 숫자 카드를 상근이가 가지고 있는지 아닌지를 구하는 프로그램을 작성하시오.

 

입력

첫째 줄에 상근이가 가지고 있는 숫자 카드의 개수 N(1 ≤ N ≤ 500,000)이 주어진다. 둘째 줄에는 숫자 카드에 적혀있는 정수가 주어진다. 숫자 카드에 적혀있는 수는 -10,000,000보다 크거나 같고, 10,000,000보다 작거나 같다. 두 숫자 카드에 같은 수가 적혀있는 경우는 없다.

셋째 줄에는 M(1 ≤ M ≤ 500,000)이 주어진다. 넷째 줄에는 상근이가 가지고 있는 숫자 카드인지 아닌지를 구해야 할 M개의 정수가 주어지며, 이 수는 공백으로 구분되어져 있다. 이 수도 -10,000,000보다 크거나 같고, 10,000,000보다 작거나 같다

 

출력

첫째 줄에 입력으로 주어진 M개의 수에 대해서, 각 수가 적힌 숫자 카드를 상근이가 가지고 있으면 1을, 아니면 0을 공백으로 구분해 출력한다.

 

예제 입력1

5
6 3 2 10 -10
8
10 9 -5 2 3 4 5 -10

 

예제 출력1

1 0 0 1 1 0 0 1

 

 


Scanner를 쓰면 통과를 못하는 문제.

BufferedReader만 써도 통과 못하는 문제.

BufferedReader와 BufferedWriter를 사용해야한다.

import java.util.Arrays;
import java.util.Scanner;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.StringTokenizer;
public class Main {
	private int N;
	private int M;
	private final int MAX = 500010;
	private int[] numbers = new int[MAX];

	// private int targets[] = new int[MAX];
	public static void main(String[] args) {
		Main main = new Main();
		try {
			main.start();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void start() throws Exception {
		//System.setIn(new FileInputStream("src/bs/input.txt"));
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
		N = Integer.parseInt(br.readLine());
		StringTokenizer st = new StringTokenizer(br.readLine());
		for (int i = 0; i < N; i++)
			numbers[i] = Integer.parseInt(st.nextToken());
		M = Integer.parseInt(br.readLine());
		st = new StringTokenizer(br.readLine());
		
		Arrays.sort(numbers, 0, N);
		for (int i = 0; i < M; i++) {
			int target =  Integer.parseInt(st.nextToken());
			if(binarySearch(target)) bw.write("1 ");
            // 이분 탐색을 해서 해당 숫자가 없는 경우
            else bw.write("0 ");
		}
        br.close();
        bw.close();
	}

	private boolean binarySearch(int target) {
		boolean found = false;
		int s = 0, e = N - 1;
		while (s <= e) {
			int divide = (s + e) / 2;
			if (numbers[divide] == target) {
				found = true;
				break;
			} else if (numbers[divide] < target) {
				s = divide + 1;
			} else {
				e = divide - 1;
			}
		}
		return found;
	}
}

출처

- https://www.acmicpc.net/problem/10815

알고리즘 종류 : 이진탐색

수찾기

시간 제한 메모리 제한
1초 256MB

 

문제

N개의 정수 A[1], A[2], …, A[N]이 주어져 있을 때, 이 안에 X라는 정수가 존재하는지 알아내는 프로그램을 작성하시오.

 

입력

첫째 줄에 자연수 N(1 ≤ N ≤ 100,000)이 주어진다. 다음 줄에는 N개의 정수 A[1], A[2], …, A[N]이 주어진다. 다음 줄에는 M(1 ≤ M ≤ 100,000)이 주어진다. 다음 줄에는 M개의 수들이 주어지는데, 이 수들이 A안에 존재하는지 알아내면 된다. 모든 정수의 범위는 -231 보다 크거나 같고 231보다 작다.

 

출력

M개의 줄에 답을 출력한다. 존재하면 1을, 존재하지 않으면 0을 출력한다.

 

예제입력1

5
4 1 5 2 3
5
1 3 7 9 5

예제출력1

1
1
0
0
1

 


이진탐색으로 풀어보자.

import java.util.Arrays;
import java.util.Scanner;

public class Main {
	private int N;
	private int M;
	private final int MAX = 100010;
	private int[] numbers = new int[MAX];

	public static void main(String[] args) {
		Main main = new Main();
		try {
			main.start();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void start() throws Exception {
		Scanner sc = new Scanner(System.in);
        N = sc.nextInt();
		for (int i = 0; i < N; i++) numbers[i] = sc.nextInt();
		M = sc.nextInt();
		
		Arrays.sort(numbers, 0, N);
		for (int i = 0; i < M; i++) {
			int target = sc.nextInt();
			System.out.println(binarySearch(target) ? 1 : 0);
		}
	}

	private boolean binarySearch(int target) {
		boolean found = false;
		int s = 0, e = N - 1;
		while (s <= e) {
			int divide = (s + e) / 2;
			if (numbers[divide] == target) {
				found = true;
				break;
			} else if (numbers[divide] < target) {
				s = divide + 1;
			} else {
				e = divide - 1;
			}
		}
		return found;
	}
    
    private int binarySearchRecursive(int s, int e, int target) {
		if(s == e) {
			return numbers[s] == target ? s : -1;
		} else if (s > e) {
			return -1;
		}
		
		int mid = (s + e) / 2;
		if(numbers[mid] < target) {
			return binarySearch(mid+1, e, target);
		} else if(numbers[mid] > target){
			return binarySearch(s, mid-1, target);
		} else {
			return mid;
		}
	}
}

 


출처

- https://www.acmicpc.net/problem/1920

알고리즘 종류 : 백트랙킹

부등호

시간 제한 메모리 제한
1초 256MB

 

문제

두 종류의 부등호 기호 ‘<’와 ‘>’가 k개 나열된 순서열 A가 있다. 우리는 이 부등호 기호 앞뒤에 서로 다른 한 자릿수 숫자를 넣어서 모든 부등호 관계를 만족시키려고 한다. 예를 들어, 제시된 부등호 순서열 A가 다음과 같다고 하자.

A ⇒ < < < > < < > < >

부등호 기호 앞뒤에 넣을 수 있는 숫자는 0부터 9까지의 정수이며 선택된 숫자는 모두 달라야 한다. 아래는 부등호 순서열 A를 만족시키는 한 예이다. 

3 < 4 < 5 < 6 > 1 < 2 < 8 > 7 < 9 > 0

이 상황에서 부등호 기호를 제거한 뒤, 숫자를 모두 붙이면 하나의 수를 만들 수 있는데 이 수를 주어진 부등호 관계를 만족시키는 정수라고 한다. 그런데 주어진 부등호 관계를 만족하는 정수는 하나 이상 존재한다. 예를 들어 3456128790 뿐만 아니라 5689023174도 아래와 같이 부등호 관계 A를 만족시킨다. 

5 < 6 < 8 < 9 > 0 < 2 < 3 > 1 < 7 > 4

여러분은 제시된 k개의 부등호 순서를 만족하는 (k+1)자리의 정수 중에서 최댓값과 최솟값을 찾아야 한다. 앞서 설명한 대로 각 부등호의 앞뒤에 들어가는 숫자는 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }중에서 선택해야 하며 선택된 숫자는 모두 달라야 한다

 

입력

첫 줄에 부등호 문자의 개수를 나타내는 정수 k가 주어진다. 그 다음 줄에는 k개의 부등호 기호가 하나의 공백을 두고 한 줄에 모두 제시된다. k의 범위는 2 ≤ k ≤ 9 이다. 

 

출력

여러분은 제시된 부등호 관계를 만족하는 k+1 자리의 최대, 최소 정수를 첫째 줄과 둘째 줄에 각각 출력해야 한다. 단 아래 예(1)과 같이 첫 자리가 0인 경우도 정수에 포함되어야 한다. 모든 입력에 답은 항상 존재하며 출력 정수는 하나의 문자열이 되도록 해야 한다. 

 

예제 입력 1

2
< >

예제 출력 1

897
021

 

예제 입력 2

9
> < < < > > > < <

예제 출력 2

9567843012
1023765489

 

출처

Olympiad > 한국정보올림피아드 > 한국정보올림피아드시․도지역본선 > 지역본선 2012 > 초등부 5번

 


import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;

public class Main {
	private final int N = 10;
	private Integer k;
	private String[] opts = new String[N];
	private Boolean[] visited = new Boolean[N];
	private List<String> result = new ArrayList<>();

	public static void main(String[] args) throws Exception {
		Main main = new Main();
		main.start();
	}

	private void isValidTest() {
		System.out.println(isValid(1, 2, ">"));
	}

	private void start() throws Exception {
		Arrays.fill(visited, false);
		//System.setIn(new FileInputStream("src/test/input.txt"));
		Scanner sc = new Scanner(System.in);
		k = sc.nextInt();
		for (int i = 0; i < k; i++) {
			opts[i] = sc.next();
			// System.out.println(opts[i]);
		}
		
		backTracking(-1, -1, "");
		Collections.sort(result);
	
		
		System.out.println(result.get(result.size()-1));
		System.out.println(result.get(0));
	}

	private void backTracking(int prev, int optIdx, String numStr) {
		if (optIdx >= k) {
			result.add(numStr);
			return;
		}
		for (int i = 0; i <= 9; i++) {
			if (!visited[i] && (optIdx == -1 || isValid(prev, i, opts[optIdx]))) {
				visited[i] = true;
				backTracking(i, optIdx + 1, numStr + i);
				visited[i] = false;
			}
		}
	}

	private Boolean isValid(int a, int b, String opt) {
		return opt.equals("<") ? a < b : a > b;
	}
}

출처

- https://www.acmicpc.net/problem/2529

알고리즘 종류 : 백트랙킹

Dessert

제한시간 메모리 제한
1000ms 32 MB

 

농부 존은 소들의 저녁식사 줄 세우는 새로운 방법을 개발 했다.

N(1~15)마리의 소들을 순서대로 세워놓은 후, 

각 소들 사이에 +, - , . 셋 중 1가지가 써져있는 냅킨을 배치해서

최종 결과가 0 이 되게 해야 하는 것이다. 

 

점(.)이 써져있는 냅킨을 통해 더 큰 수를 만들 수 있게 된다. 

아래와 같은 경우를 보자. (ps .이 써져있는 냅킨은 '공백'이라고 생각하면 된다.)

 

1 - 2 . 3 - 4 . 5 + 6 . 7

 

이와 같은 배치는 1-23-45+67 을 나타낸다. 

결과는 0 이다. 

10.11은 1011 로 해석된다.

 

입력형식

첫 번째 줄에는 소들의 수 N이 입력된다.

 

출력형식

처음 20줄에 대해 가능한 20가지 답을 출력하는데, 사전 순으로 앞선 것을 출력한다.

순서는 +가 가장 앞서고 -와 .이 순서대로 뒤따른다.
답이 20개 미만이면 가능한 답을 모두 출력한다. 

마지막 줄에는 가능한 답의 총 가지 수를 출력한다.

 

입력 예

7

 

출력 예

1 + 2 - 3 + 4 - 5 - 6 + 7 
1 + 2 - 3 - 4 + 5 + 6 - 7 
1 - 2 + 3 + 4 - 5 + 6 - 7 
1 - 2 - 3 - 4 - 5 + 6 + 7 
1 - 2 . 3 + 4 + 5 + 6 + 7 
1 - 2 . 3 - 4 . 5 + 6 . 7 
6

 


public class Main {
	private int totalCnt = 0;

	public static void main(String[] args) throws Exception {
		Main main = new Main();
		main.run();
		
	}
	
	private void run() throws Exception {
		System.setIn(new FileInputStream("src/test/input.txt"));
		Scanner sc = new Scanner(System.in);
		int N = sc.nextInt();
		String[] numbersAndOpts = new String[2 * N - 1];
		numbersAndOpts[0] = "1";
		fullSearch(numbersAndOpts, 2, 1, 2 * N - 1);
		System.out.println(totalCnt);
	}


	private void fullSearch(String[] numbersAndOpts, int cur, int idx, int maxIdx) {
		if (idx >= maxIdx) {
			if (checkEquationIsZero(numbersAndOpts)) {
				totalCnt++;
				if(totalCnt <= 30) printEquation(numbersAndOpts);
			}
			return;
		}

		numbersAndOpts[idx] = "+";
		numbersAndOpts[idx + 1] = Integer.toString(cur);
		;
		fullSearch(numbersAndOpts, cur + 1, idx + 2, maxIdx);

		numbersAndOpts[idx] = "-";
		numbersAndOpts[idx + 1] = Integer.toString(cur);
		;
		fullSearch(numbersAndOpts, cur + 1, idx + 2, maxIdx);

		numbersAndOpts[idx] = ".";
		numbersAndOpts[idx + 1] = Integer.toString(cur);
		;
		fullSearch(numbersAndOpts, cur + 1, idx + 2, maxIdx);
		
	}

	private Boolean checkEquationIsZero(String[] numbersAndOpts) {
		StringBuilder sb = new StringBuilder();
		
		int nextIdx = getNumberStr(numbersAndOpts, sb, 0);
		Double sum = Double.parseDouble(sb.toString());
		emptyStringBuilder(sb);
		while (nextIdx < numbersAndOpts.length) {
			
			if (numbersAndOpts[nextIdx].equals("+")) {
				nextIdx = getNumberStr(numbersAndOpts, sb, nextIdx + 1);
				sum += Double.parseDouble(sb.toString());
				emptyStringBuilder(sb);
					
			} else if (numbersAndOpts[nextIdx].equals("-")) {
				nextIdx = getNumberStr(numbersAndOpts, sb, nextIdx + 1);
				sum -= Double.parseDouble(sb.toString());
				emptyStringBuilder(sb);
			}
		}

		return sum.equals(0.0) ? Boolean.TRUE : Boolean.FALSE;
		// Double.parseDouble();
	}
	private void emptyStringBuilder(StringBuilder sb) {
		sb.setLength(0);
	}

	private int getNumberStr(String[] numbersAndOpts, StringBuilder sb, int cur) {
		sb.append(numbersAndOpts[cur]);
		int i = cur + 1;
		while(i < numbersAndOpts.length - 1 && numbersAndOpts[i].equals(".")) {
			sb.append(numbersAndOpts[i + 1]);
			i += 2;
		}
		return i;
	}
	
	private void printEquation(String[] numbersAndOpts) {
		for (int i = 0; i < numbersAndOpts.length; i++) {
			System.out.print(numbersAndOpts[i] + " ");
		}
		System.out.println("");
	}

	private void test() {
		String[] numbersAndOpts = {"1",".","2",".","3",".","4"};
		StringBuilder sb = new StringBuilder();
		System.out.println(getNumberStr(numbersAndOpts, sb, 0));
	}
	
	private void testCheckEquationIsZero() {
		String[] numbersAndOpts = {"1",".","2","-","1",".","2"};
		System.out.println(checkEquationIsZero(numbersAndOpts));
	}
	
	private String[] deepClone(String[] numbersAndOpts) {
		String[] copy = new String[numbersAndOpts.length];
		for (int i = 0; i < numbersAndOpts.length; i++) {
			copy[i] = numbersAndOpts[i];
		}
		return copy;
	}

	

	private void start() {
		String[] my = new String[10];
		my[0] = "hi";

		System.out.println("=====Array========");
		System.out.println(my[0]);

		changeContents(my);

		System.out.println(my[0]);

		System.out.println("=====Wrapper========");

		Integer num = new Integer(3);

		System.out.println(num);
		changeNumber(num);
		System.out.println(num);

		System.out.println("========Object===========");
		Obj obj = new Obj();
		obj.num = 3;

		System.out.println(obj.num);
		changeObj(obj);
		System.out.println(obj.num);

		System.out.println("==========Collection - List ==============");
		List<Integer> li = new ArrayList<>();
		System.out.println(li.size());
		changeList(li);
		System.out.println(li.size());

	}

	class Obj {
		public int num;
	}

	private void changeContents(String[] args) {
		args[0] = "test1";
		args[1] = "test2";
	}

	private void changeNumber(Integer num) {
		num = 13;
	}

	private void changeObj(Obj obj) {
		obj.num = 13;
	}

	private void changeList(List<Integer> li) {
		li.add(3);
	}
}

 


출처

http://www.jungol.co.kr/bbs/board.php?bo_table=pbank&wr_id=463&sca=9040

+ Recent posts