Algorithm/λ°±μ€€

λ°±μ€€ 2467 - μš©μ•‘ (이뢄탐색, νˆ¬ν¬μΈν„°)

Edlin 2022. 4. 18. 18:13

πŸ‘†πŸ‘† 더보기λ₯Ό λˆ„λ₯΄μ‹œλ©΄ 문제 링크λ₯Ό ν™•μΈν•˜μ‹€ 수 μžˆμŠ΅λ‹ˆλ‹€.

문제 μš”μ•½

- μ‚°μ„± μš©μ•‘κ³Ό μ•ŒμΉΌλ¦¬μ„± μš©μ•‘μ˜ νŠΉμ„±κ°’μ΄ μ •λ ¬λœ μˆœμ„œλ‘œ μ£Όμ–΄μ§„λ‹€.

- 이 쀑 두 개의 μ„œλ‘œ λ‹€λ₯Έ μš©μ•‘μ„ ν˜Όν•©ν•˜μ—¬ νŠΉμ„±κ°’μ΄ 0에 κ°€κΉŒμš΄ μš©μ•‘μ„ λ§Œλ“€μ–΄ λ‚΄λŠ” 두 μš©μ•‘μ„ 좜λ ₯ν•˜λΌ.

* ν˜Όν•©ν•œ μš©μ•‘μ˜ νŠΉμ„±κ°’: ν˜Όν•©μ— μ‚¬μš©λœ 각 μš©μ•‘μ˜ νŠΉμ„±κ°’μ˜ ν•© 

 


μ œν•œ 쑰건

- 전체 μš©μ•‘μ˜ 수 (2≤ N ≤ 100,000)

(100,000 κ°€μ§€ 쀑 2κ°€μ§€ 경우의 수λ₯Ό 찾으면 경우의 μˆ˜κ°€ μƒλ‹Ήνžˆ λ§Žμ•„μ Έ 1μ΄ˆλ§Œμ— 문제λ₯Ό 풀기에 무리가 μžˆλ‹€.)

- μš©μ•‘μ˜ νŠΉμ„± κ°’ (-1,000,000,000 ≤ M ≤ 1,000,000,000) (Long νƒ€μž…)


아이디어 

- Two pointer (μ™Όμͺ½ 인덱슀, 였λ₯Έμͺ½ 인덱슀)

- μ™Όμͺ½ μΈλ±μŠ€κ°€ κ°€λ¦¬ν‚€λŠ” νŠΉμ„± κ°’κ³Ό 였λ₯Έμͺ½ μΈλ±μŠ€κ°€ κ°€λ¦¬ν‚€λŠ” νŠΉμ„± κ°’μ˜ 합이 0보닀 μž‘μœΌλ©΄ μ™Όμͺ½ 인덱슀 κ°’ 증가

∡ (μ™Όμͺ½ μΈλ±μŠ€κ°€ κ°€λ¦¬ν‚€λŠ” κ°’ + 였λ₯Έμͺ½ μΈλ±μŠ€κ°€ κ°€λ¦¬ν‚€λŠ” κ°’)의 μ ˆλŒ“κ°’μ΄ 0에 κ°€κΉŒμ›Œ μ Έμ•Όν•˜κΈ° λ•Œλ¬Έμ—

- νŠΉμ„± κ°’μ˜ 합이 0보닀 크면 였λ₯Έμͺ½ 인덱슀의 값이 더 ν¬λ―€λ‘œ 였λ₯Έμͺ½ 인덱슀 κ°’ κ°μ†Œ

- 두 νŠΉμ„± κ°’μ˜ ν•© μ ˆλŒ“κ°’μ΄ 0에 κ°€μž₯ κ°€κΉŒμš΄ 두 수 좜λ ₯

∡ νŠΉμ„± κ°’μ˜ 합에 μ ˆλŒ“κ°’μ„ μ·¨ν•˜λŠ” μ΄μœ λŠ” 음의 κ°’κ³Ό μ–‘μ˜ 값에 상관 없이 0에 κ°€κΉŒμ΄ μœ„μΉ˜ν•˜λŠ” 수λ₯Ό μ°ΎκΈ° μœ„ν•΄μ„œλ‹€.


μ½”λ“œ (Java)

import java.util.Scanner;

public class BS_boj_2467 {

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

		int N = sc.nextInt();
		long[] items = new long[N];

		for (int i = 0; i < N; i++) {
			items[i] = sc.nextLong();
		}

		// 1. μ •λ ¬ (ν•„μš” XX) - 이미 μ˜€λ¦„μ°¨μˆœμœΌλ‘œ μž…λ ₯이 μ£Όμ–΄μ§„λ‹€.

		int left = 0; // λ°°μ—΄ μ™Όμͺ½ 끝 index
		int right = N - 1; // λ°°μ—΄ 였λ₯Έμͺ½ 끝 index

		long ans1 = 0, ans2 = 0; // 좜λ ₯ν•  두 수 

		long min = Integer.MAX_VALUE; // 0에 κ°€κΉŒμš΄ κ°’ (μ ˆλŒ“κ°’)

		// 2. 이뢄탐색 
		// leftκ°€ 컀지고 rightκ°€ 쀄어듀닀보면 left == rightκ°€ κ°™μ•„μ§€λŠ” μˆœκ°„μ΄ μ˜¨λ‹€.
		// left와 rightκ°€ κ°™μ•„μ§ˆ 경우 같은 수λ₯Ό κ°€λ¦¬ν‚€λŠ” 것을 μ˜λ―Έν•˜κΈ° λ•Œλ¬Έμ—
		// left <= right κ°€ μ•„λ‹Œ, left < right κ°€ λ˜μ–΄μ•Ό ν•œλ‹€.
		while (left < right) {
			long sum = items[left] + items[right]; // 두 인덱슀의 ν•©

			if (min > Math.abs(sum)) { 
				// μ ˆλŒ“κ°’μ„ μ΄μš©ν•˜μ§€ μ•ŠμœΌλ©΄, min은 -κ°€ 될 수 μžˆλ‹€.
				// -λ“  +λ“  0에 κ°€κΉŒμš΄ 값을 μ°ΎλŠ” κ²ƒμ΄λ―€λ‘œ μ ˆλŒ“κ°’μ„ μ·¨ν•΄μ€€λ‹€. 
				min = Math.abs(sum);
				ans1 = items[left];
				ans2 = items[right];
			}

			// sum이 0보닀 μž‘μ•˜λ‹€λŠ” 것은 μ™Όμͺ½ 값이 였λ₯Έμͺ½ 값보닀 μ ˆλŒ“κ°’μ„ μ·¨ν–ˆμ„ λ•Œ ν¬λ‹€λŠ” 것을 μ˜λ―Έν•œλ‹€.
			// μ™Όμͺ½μ„ μ¦κ°€μ‹œμΌœ sum의 수λ₯Ό 쀄인닀. 
			if (sum < 0)
				left++;
			else
				right--;
			// sum이 0보닀 ν¬λ‹€λŠ” 것은 였λ₯Έμͺ½ 값이 μ™Όμͺ½ 값보닀 μ ˆλŒ“κ°’μ„ μ·¨ν–ˆμ„ λ•Œ ν¬λ‹€λŠ” 것을 μ˜λ―Έν•œλ‹€.
			// 였λ₯Έμͺ½μ„ κ°μ†Œμ‹œμΌœ sum의 수λ₯Ό 쀄인닀. (sum의 수λ₯Ό 쀄여야 0에 κ°€κΉŒμš΄ 값을 찾을 수 μžˆλ‹€.)
		}

		System.out.println(ans1 + " " + ans2);
	}
}