알고리즘/백준

1253_좋다

베리영young 2024. 6. 13. 00:11

사용 알고리즘: 투 포인터

사용 언어: java

 

테스트 통과되지 못한 코드 (시간 초과)

package week03;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Main_bj_1253_좋다 {
	static int n;
	static int[] numbers;
	
	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		n = Integer.parseInt(br.readLine());
		numbers = new int[n];
		StringTokenizer st = new StringTokenizer(br.readLine());
		for(int i=0; i<n; i++) {
			numbers[i] = Integer.parseInt(st.nextToken());
		}
		Arrays.sort(numbers);
		//입 력 끝
		
		int ans = 0; //좋은 수의 개수 = 답
		
		//어차피 맨 앞 두 수는 좋을 수가 없음
		for (int i=2; i<n; i++) {
			if ( isGoodNumber(i) ) ans++;
		}
		
		System.out.println(ans);
	}

	private static boolean isGoodNumber(int idx) { //좋은 수인지 판별
		int curNumber = numbers[idx];
		
		int left = 0;
		int right = idx - 1;
		
		while (left < right) {
			int smaller = numbers[left];
			int bigger = numbers[right];
			
			if (smaller + bigger == curNumber) {
				return true; //좋은 수가 된다면 트루를 리턴
			}
			
			if (smaller + bigger < curNumber) { //목표값 보다 작은 수가 나온다면, left를 증가시키기
				smaller ++;
			}
			else { //목표값 보다 큰 수가 나온다면, right를 감소시키기
				bigger --;
			}
			
		}
		return false;
	}

}

 

 

맞는 답

package week03;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

/**
 * 헐!! 
 * 음수가 나오면 나보다 큰 수도 사용될 수 있다!!
 *
 */

public class Main_bj_1253_좋다 {
	static int n;
	static int[] numbers;
	
	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		n = Integer.parseInt(br.readLine());
		numbers = new int[n];
		StringTokenizer st = new StringTokenizer(br.readLine());
		for(int i=0; i<n; i++) {
			numbers[i] = Integer.parseInt(st.nextToken());
		}
		Arrays.sort(numbers);
		//입 력 끝
		
		int ans = 0; //좋은 수의 개수 = 답
		
		for (int i=0; i<n; i++) {
//			System.out.println(i+" 번째 테스트 시작!");
			if ( isGoodNumber(i) ) ans++;
		}
		
		System.out.println(ans);
	}

	private static boolean isGoodNumber(int idx) { //좋은 수인지 판별
		int curNumber = numbers[idx];
		
		int left = 0;
		int right = n - 1;
		
		while (true) {
			if (right == idx) right--;
			if (left == idx) left++;
			
			if (left >= right) break;
			
			int middle = (left + right) / 2;
			
			int smaller = numbers[left];
			int bigger = numbers[right];
			
			if (smaller + bigger == curNumber) {
				return true; //좋은 수가 된다면 트루를 리턴
			}
			
			if (smaller + bigger < curNumber) { //목표값 보다 작은 수가 나온다면, left를 증가시키기
				left++ ;
			}
			else { //목표값 보다 큰 수가 나온다면, right를 감소시키기
				right--;
			}
//			System.out.println("left and right: " + left + " "+right);
		}
		return false;
	}

}

 

요인 분석:

1. 인덱스를 움직여야 하는데 왜 수를 움직였지?..

2. 음수가 나올 수 있으니, 타겟 인덱스 보다 큰 인덱스에서도 확인을 해야 한다.

3. 2의 이유로 돌다보면 타겟 인덱스에 right나 left가 걸치는 때가 오는데, while의 조건이 left < right라고 해도 인덱스 조정이 들어가게 되면 left == right가 되는 경우가 발생할 수 있다.

그래서 종료 조건을 while문 자체에 두지 않고, 인덱스 조정 후 if문을 따로 두어서 break를 건다.