거북이의 기술블로그 2024. 10. 23. 13:08
1. 문제
2. 문제 분석
3. 슈도코드
4. 구현

문제

주어진 N (1 <= N <= 2000) 개의 수 중, 두 수의 합으로 표현되는 수 찾기
- 숫자 범위 : ( 숫자 <= 1,000,000,000 )
- 2초 이내 풀어낼 것 ( CPU 계산 : 1초에 1억번 연산 )
- N세제곱은 시간 오버이므로, 주의하며 구현

 

문제분석

  • N제곱 안에 문제를 풀어내야함 (시간제한)
  • 투포인터 ( O(n) )를 사용하여 , 두수의 합으로 표현되는 수 찾기 가능
    • 단, 두수의 합으로 표현되는 수의 개수를 찾는것이기에  한가지 조합만 있으면 됨
[투포인터]
* 투포인터 사용 전, 오름차순 정렬이 전제 조건임
1. Arr[i] + Arr[j] < M  //  i 증가
2. Arr[i] + Arr[j] > M  //  j 감소
3. Arr[i] + Arr[j] == M //  count 증가, i 증가, j 감소 

 

슈도코드

N (배열의 개수) 

for (N만큼 반복)
{
    A배열에 데이터 저장
}

A배열 정렬하기

for(N만큼 반복)
{
    변수 초기화 // (찾고자 하는 값: A[k] , 포인터 : i,j)
     while(i < j){
     {
          if( A[i] + A[j] == A[k] )
                두 포인터 i,j 가, k가 아닐때 결과값에 반영(조합 찾기 성공) 및 while 문 종료
                두 포인터 i,j 가, k가 맞을때 포인터 변경 및 계속 수행
          else if (k > M) 포인터 i 증가
          else 포인터 j 증가
       }
}

좋은 수의 개수 출력

 

구현

  • 투포인터에서 j 초기화 값을 "size-1"로 둔 것은 전 범위를 기준으로 탐색하려는 목적 ( 음수도 가능하기에 arr[k] 보다 큰수도 고려해야함)
  • k인덱스를 포함하면 안되므로, 제거해줘야하는 조건이 필요
    • 두개의 합을 이루는 "숫자"를 찾는것이므로, 해당 숫자가 두개의 합 조합에 들어가면 안됨
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

public class App {
    public static void main(String[] args) throws Exception {
        
        BufferedReader buf = new BufferedReader(new InputStreamReader(System.in));
        
        int size =Integer.parseInt(buf.readLine());
        int []arr = new int[size];
        
        StringTokenizer st = new StringTokenizer(buf.readLine());

        for(int i=0; i<size; i++){
            if (st.hasMoreTokens()){
                arr[i] = Integer.parseInt(st.nextToken());
            }else{
                System.out.println("StringTokenizer 오류");
                break;
            }
        }
        
        Arrays.sort(arr);
        
        int result = 0;
        for(int k=0; k<size; k++){
            long find = arr[k];
            int i = 0;
            int j = size-1;
            
            while (i<j){
                if ( arr[i] + arr[j] == find ){
                    if (i != k && j != k){
                        result++;
                        break;
                    }else if(i == k){
                        i++;
                    }else if(j==k){
                        j--;
                    }
                }else if (arr[i] + arr[j] > find) {
                    j--;
                }else{
                    i++;
                }
            }
            
        }

        System.out.println("Result : " + result);

    }
}