일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 2년차개발자
- 개발자
- gin logger
- gopath 환경변수
- go panic
- gin middleware
- go 맥 air 환경변수
- go디자인패턴
- go clean architecture
- go recover
- go 마스코트
- go 맥 air
- clean architecture middleware
- go middleware
- 좀비고루틴
- go
- go 환경변수
- go channel
- go 맥
- air 환경변수
- go 대기그룹
- 골랑 고퍼
- gin recovery
- 고루틴 채널
- golang gopher
- git
- 신입개발자
- go 캐릭터
- go air
- go air 환경변수
- Today
- Total
뽀미의 개발노트
인프런 3-2. 공통원소 구하기 (자바) 본문
[문제]
A, B 두 개의 집합이 주어지면 두 집합의 공통 원소를 추출하여 오름차순으로 출력하는 프로그램을 작성하세요.
[입력]
첫 번째 줄에 집합 A의 크기 N(1<=N<=30,000)이 주어집니다.
두 번째 줄에 N개의 원소가 주어집니다. 원소가 중복되어 주어지지 않습니다.
세 번째 줄에 집합 B의 크기 M(1<=M<=30,000)이 주어집니다.
네 번째 줄에 M개의 원소가 주어집니다. 원소가 중복되어 주어지지 않습니다.
각 집합의 원소는 1,000,000,000이하의 자연수입니다.
[출력]
두 집합의 공통원소를 오름차순 정렬하여 출력합니다.
[예시 입력 1]
5
1 3 9 5 2
5
3 2 5 7 8
[예시 출력 1]
2 3 5
[문제 풀이 과정]
음 일단 얘도 투포인터로 풀면 될 것같다.
근데 얘는 이중 반복문을 돌려야될 것 같은데??
근데 집합의 크기가 원소가 3만개까지 들어갈 수 있는데
이중 반복문을 돌려도 되는걸까?
그리고 이중 반복문으로 풀려면 포인터라는게 굳이 필요한걸까?
어차피 반복문 돌때 i 같은 변수가 필요할 텐데 말이야
아니면 이전에 풀었던 문제처럼
일단 두 집합에 있는 원소들을 한 배열에 넣어서
오름차순으로 정렬하고 그중에서 똑같은게 뭐있는지 찾는건가..?
근데 그러기엔 배열 두개가 각각 오름차순으로 주어지지 않았는데..
그럼 이중 for문으로 푸는게 맞나?? 일단 생각나는게
이거밖에 없으니까 이중 포문으로 풀어보자!!!
[이중 for문으로 풀어서 타임 리밋 뜬 코드]
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int[] a = new int[N];
for(int i = 0 ; i < N ; i++) {
a[i] = sc.nextInt(); // a배열 따로
}
int M = sc.nextInt();
int[] b = new int[M];
for(int i = 0 ; i < M ; i++) {
b[i] = sc.nextInt(); // b배열 따로
}
List<Integer> answer = new ArrayList<>(); // 정답리스트
for(int i = 0 ; i < N ; i++) {
for(int j = 0 ; j < M ; j++) {
if(b[j] == a[i]) {
answer.add(a[i]);
}
}
}
Collections.sort(answer);
for(int x : answer) {
System.out.print(x + " ");
}
}
}
아... 이중 포문으로 푸니까 타임 리밋 나네...
음 그럼 뭔가 투포인터로 풀어야되는 문제라는 건데.. 어떻게 할까?
음.. 그럼 일단 두개의 배열 모두 오름차순으로 정렬 해보자
1 2 3 5 9
2 3 5 7 8
이렇게!!
그리고 a[p1] < b[p2]이면 a[p1]은 절대 똑같은 값이
나올리가 없으므로 p1++ 시키고 다음으로 넘어가기
a[p1] == b[p2]이면 똑같은 값 나왔으니까 둘다 p1++, p2++ 시키기
그리고 a[p1] > b[p2]이면 b[p2]는 절대 똑같은 값이
나올리가 없으므로 p2++ 시키고 다음으로 넘어가기!!
이렇게 투포인터를 이용해서 풀면 이중for문보다는 시간이
덜 걸리지 않을까??
[투포인터로 풀어서 통과한 코드!!]
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int[] a = new int[N];
for(int i = 0 ; i < N ; i++) {
a[i] = sc.nextInt(); // a배열 따로
}
int M = sc.nextInt();
int[] b = new int[M];
for(int i = 0 ; i < M ; i++) {
b[i] = sc.nextInt(); // b배열 따로
}
Arrays.sort(a);
Arrays.sort(b);
// a배열과 b배열 모두 오름차순으로 정렬
int p1 = 0, p2 = 0; // 포인터 두개 만들어주기
// 포인터들은 각 배열의 인덱스를 가리킴.
List<Integer> answer = new ArrayList<>(); // 정답리스트
while(p1 < N && p2 < M) {
if(a[p1] < b[p2]) {
p1++;
// 그럼 a[p1]은 절대 똑같은 값이 나올리가 없으므로
// p1은 그 다음을 가리키기
} else if(a[p1] == b[p2]){
answer.add(a[p1]);
p1++;
p2++;
// 둘이 똑같으면 정답 리스트에 넣고
// p1이랑 p2둘다 다음걸로 넘어가서 비교하기
} else {
p2++;
// 그럼 b[p2]는 절대 똑같은 값이 나올리가 없으므로
// p2는 그 다음을 가리키기
}
// p1 == N이거나 p2 == M이면 둘중 한 배열을 다 쓴것!
// 그럼 똑같은 수가 절대 없다는 것이므로 여기서 반복문 끝.
}
for(int x : answer) {
System.out.print(x + " ");
}
}
}
오 이렇게 푸니까 맞네!!
시간을 비교해보니 처음 이중 for문으로 풀었을 때는 1974ms걸렸는데
투포인터로 푸니 703ms가 걸렸다!
[후기]
항상 문제 푸는 방법으로 난 이중 for문밖에 생각이 안나던데 투포인터로 하니까 시간이 훨씬 덜 걸리네!! 좋은 스킬을 알게 된 것 같다 앞으로 투포인터 잘 써먹어야징~!!
'Algorithm_Test' 카테고리의 다른 글
인프런 3-1. 두 배열 합치기 (자바) (1) | 2023.09.07 |
---|---|
인프런 2-2. 보이는 학생 (자바) (1) | 2023.09.06 |
인프런 2-1. 큰 수 출력하기 (자바) (1) | 2023.09.05 |
인프런 1-2. 대소문자 변환 (자바) (0) | 2023.09.04 |
인프런 1-1. 문자 찾기 (자바) (0) | 2023.09.04 |