앞선 글들과 마찬가지 방법으로 풀었는데 12%에서 시간 초과가 나서

아래와 같이 바이너리 서치 방법으로 풀었는데 75% 대에서 다시 시간초과가 났다.

 

import java.util.*;
import java.io.*;

public class Main {
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int size = in.nextInt();
		int m = in.nextInt();
		int n = in.nextInt();
		int A[] = new int[m];
		int B[] = new int[n];

		int aSum = 0;
		for (int i = 0; i < m; i++) {
			A[i] = in.nextInt();
			aSum += A[i];
		}
		int bSum = 0;
		for (int i = 0; i < n; i++) {
			B[i] = in.nextInt();
			bSum += B[i];
		}

		ArrayList<Integer> aPizza = new ArrayList<Integer>();
		ArrayList<Integer> bPizza = new ArrayList<Integer>();

		findAllSums(A, aPizza);
		findAllSums(B, bPizza);
		aPizza.add(aSum);
		bPizza.add(bSum);

		Collections.sort(aPizza);
		Collections.sort(bPizza);

		long ans = 0;
		for (int sum : aPizza) {
			int cnt = binarySearch(bPizza, size - sum);

			if (cnt != -1) {
				ans += cnt;
			}
		}

		System.out.println(ans);
	}

	public static int binarySearch(ArrayList<Integer> list, int target) {
		int left = 0;
		int right = list.size() - 1;
		int mid = (left + right) / 2;
		while (left <= right) {
			mid = (left + right) / 2;

			if (target == list.get(mid)) {
				break;
			} else if (target < list.get(mid)) {
				right = mid - 1;
			} else {
				left = mid + 1;
			}
		}

		if (target == list.get(mid)) {
			int ans = 1;
			int index = mid - 1;
			while (index >= 0) {
				if (target == list.get(index)) {
					ans++;
				} else {
					break;
				}
				index--;
			}
			index = mid + 1;
			while (index < list.size()) {
				if (target == list.get(index)) {
					ans++;
				} else {
					break;
				}
				index++;
			}
			return ans;
		}

		return -1;
	}

	public static void findAllSums(int arr[], ArrayList<Integer> list) {
		int length = arr.length;
		
		for (int i = 0; i < length; i++) {
			int sum = 0;
			int index = i;
			while (true) {
				sum += arr[index % length];
				list.add(sum);
				index++;

				if (index - i + 1 == length) {
					break;
				}
			}
		}
		list.add(0);

		return;
	}
}

 

LinkedList에서의 데이터의 삽입, 삭제 시에는 ArrayList와 비교해 굉장히 빠른데,

LinkedList는 이전 노드와 다음 노드를 참조하는 상태만 변경하면 되기 때문이다.

삽입, 삭제가 일어날 때 O(1)의 시작 복잡도를 가진다.

반면 ArrayList의 경우 삽입, 삭제 이후 다른 데이터를 복사해야 하기 때문에 최악의 경우 O(N) 의 성능을 내게 된다.

그래서 LinkedList로 바꿨는데 그래도 시간초과는 똑같음

 

이진 탐색에서 시간이 걸리는 것 같아서 HashMap에 나올 수 있는 피자의 넓이를 넣어놓고 바로 가져올 수 있도록 바꿨다.

import java.util.*;

public class Main {
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int size = in.nextInt();
		int m = in.nextInt();
		int n = in.nextInt();
		int A[] = new int[m];
		int B[] = new int[n];

		int aSum = 0;
		for (int i = 0; i < m; i++) {
			A[i] = in.nextInt();
			aSum += A[i];
		}
		int bSum = 0;
		for (int i = 0; i < n; i++) {
			B[i] = in.nextInt();
			bSum += B[i];
		}

		HashMap<Integer, Integer> aPizza = new HashMap<Integer, Integer>();
		HashMap<Integer, Integer> bPizza = new HashMap<Integer, Integer>();

		findAllSums(A, aPizza);
		findAllSums(B, bPizza);

		aPizza.put(aSum, 1);
		bPizza.put(bSum, 1);
		aPizza.put(0, 1);
		bPizza.put(0, 1);

		long ans = 0;

		for (int sum : aPizza.keySet()) {
			int cnt = bPizza.getOrDefault(size - sum, -1);
			if (cnt != -1) {
				ans += cnt * aPizza.get(sum);
			}
		}

		System.out.println(ans);
	}

	public static void findAllSums(int arr[], HashMap<Integer, Integer> list) {
		int length = arr.length;

		for (int i = 0; i < length; i++) {
			int sum = 0;
			int index = i;
			while (true) {
				sum += arr[index % length];
				list.putIfAbsent(sum, 0);
				list.replace(sum, list.get(sum) + 1);
				index++;

				if (index - i + 1 >= length) {
					break;
				}
			}
		}
		return;
	}
}

'알고리즘 공부 > boj' 카테고리의 다른 글

boj 11437: LCA  (0) 2020.07.15
boj 2143: 두 배열의 합  (0) 2020.07.15
boj 7453: 합이 0인 네 정수  (0) 2020.07.13
boj 1208: 부분집합의 합2  (0) 2020.07.13
boj 1956: 운동  (0) 2020.07.10

+ Recent posts