|
[제한사항]
- nums에 들어있는 숫자의 개수는 3개 이상 50개 이하입니다.
- nums의 각 원소는 1 이상 1,000 이하의 자연수이며, 중복된 숫자가 들어있지 않습니다.
[입출력 예]

추측)
소수의 개념은 1과 그 값 자체만 약수로 가지는 수다.
일단 nums에서 3개의 수를 골라 더하는 경우의 수를 구하려면 for문이 3개나 돌아야하는 데 너무 비효율적이다.
다른 방법이 있을거라 생각한다. 일단은 for문으로 구현 먼저 해보고 검색해서 개선하는 방향으로 가자
소스코드)
* 1차) 실패 - 역시나 효율성이 너무 안좋아서 메모리 초과, 런타임 에러 등등 다양한 실패로 테스트에서 단하나 통과한 케이스
import java.util.ArrayList;
class Solution {
public int solution(int[] nums) {
int sum = 0;
// 이 숫자의 개수로 만들수 있는 전체 경우의 수
int caseCnt = 0;
for (int x=0; x<3; x++){
if(x==0){
caseCnt = nums.length;
continue;
}
caseCnt *= nums.length-x;
}
// 이 숫자들 중 3개 값의 합을 해당 인덱스에 넣기 (중복은 피한다)
int[] flagArr = new int[caseCnt];
for(int i=0; i<nums.length; i++){
for(int j=i+1; j<nums.length; j++){
for(int k=j+1; k< nums.length; k++){
if(flagArr[nums[i] + nums[j] + nums[k]] == 1){
continue;
}
flagArr[nums[i] + nums[j] + nums[k]] = nums[i] + nums[j] + nums[k];
}
}
}
// 합의 경우의 수만 모으기
ArrayList<Integer> sumCase = new ArrayList<>();
for(int y=0; y<flagArr.length; y++){
if(flagArr[y] != 0){
sumCase.add(flagArr[y]);
}
}
// 소수를 어떻게 가리나
int primeNumCnt = 0;
int numCnt = 0;
for(int z=0; z<sumCase.size(); z++){
int sumOne = sumCase.get(z);
for(int a=2; a<sumOne; a++){
double share = (double) sumOne / a;
if(share - (int) share == 0) {
numCnt++;
}
}
if(numCnt == 0){
primeNumCnt++;
}
numCnt=0;
}
return primeNumCnt;
}
}
* 2차) 실패
public int solution(int[] nums) {
int sum = 0;
int numsLen = nums.length;
// 중복 값을 피하기위한 배열 생성
Arrays.sort(nums);
int[] numArr = new int[nums[numsLen-1]+nums[numsLen-2]+nums[numsLen-3]+1];
// for문을 돌릴 횟수는 nCr로 구한다.
int sumCaseFull = (numsLen*(numsLen-1)*(numsLen-2)) / 6; // 조합 공식 nCr = nPr/r! // n숫자개수 r선택개수
for(int i=0; i<numsLen; i++){
for(int j=i+1; j<numsLen; j++){
for(int k=j+1; k<numsLen; k++){
if(numArr[nums[i] + nums[j] + nums[k]] == nums[i] + nums[j] + nums[k]){
continue;
}
numArr[nums[i] + nums[j] + nums[k]] = nums[i] + nums[j] + nums[k];
}
}
}
// 합의 경우의 수만 모으기
ArrayList<Integer> sumCase = new ArrayList<>();
for(int y=0; y<numArr.length; y++){
if(numArr[y] != 0){
sumCase.add(numArr[y]);
}
}
// 소수를 어떻게 가리나
int primeNumCnt = 0;
int numCnt = 0;
for(int z=0; z<sumCase.size(); z++){
int sumOne = sumCase.get(z);
for(int a=2; a<sumOne; a++){
if(sumOne%a == 0) {
numCnt++;
}
}
if(numCnt == 0){
primeNumCnt++;
}
numCnt=0;
}
return primeNumCnt;
}
* 3차) 성공 [메모리: 82.8 MB, 시간: 0.03 ms]
public int solution(int[] nums) {
int sum = 0;
int numsLen = nums.length;
// for문을 돌릴 횟수는 nCr로 구한다.
ArrayList<Integer> sumArr = new ArrayList<>();
int sumCaseFull = (numsLen*(numsLen-1)*(numsLen-2)) / 6; // 조합 공식 nCr = nPr/r! // n숫자개수 r선택개수
for(int i=0; i<numsLen; i++){
for(int j=i+1; j<numsLen; j++){
for(int k=j+1; k<numsLen; k++){
sumArr.add(nums[i] + nums[j] + nums[k]);
}
}
}
// 소수를 어떻게 가리나
int primeNumCnt = 0;
int numCnt = 0;
for(int z=0; z<sumArr.size(); z++){
int sumOne = sumArr.get(z);
for(int a=2; a<sumOne; a++){
if(sumOne%a == 0) {
numCnt++;
}
}
if(numCnt == 0){
primeNumCnt++;
}
numCnt=0;
}
return primeNumCnt;
}
리뷰)
1차) 오로지 알고있는 한도내에서 구현한 코드. 일단 경우의 수를 구하는 공식도 틀렸고 효율성이 너무 안좋다 생각이 들어서 통과할거란 생각은 안했다. 일단 입출력 예의 result를 출력해 낼 수 있는가만 생각해봤다.
2차) 조합 공식을 알게 되었다 (지식+1) 조합 공식을 이용해 경우의 수를 구해 적용했다.
3차) 아니!!!! 합의 수가 같은건 일부러 제외했는데 ㅠㅠㅠㅠㅠ 오히려 중복을 제거하면 안됬던 거였다 ㅠㅠㅠ 문제를 잘보자 ㅠㅠㅠ
+ 조합 알고리즘:
[알고리즘 - 조합] 조합과 조합 알고리즘
조합 알고리즘 개요 조합 알고리즘에 대해 알아보기 전에, 먼저 조합에 대해 알아보자. 조합이란? n개의 숫자 중, r개의 숫자를 순서없이 뽑는 것 공식 ‘하나의 원소를 선택할 경우’ + ‘하나의
taegyunwoo.github.io
정승제 쌤의 조합 강의 :
'Coding Test > Algorithm' 카테고리의 다른 글
| Programmers] 신규 아이디 추천 (0) | 2022.11.23 |
|---|---|
| Programmers] 시저 암호 (0) | 2022.11.23 |
| Programmers] 숫자 문자열과 영단어 (0) | 2022.11.22 |
| Programmers] 문자열 내림차순으로 배치하기 (0) | 2022.11.22 |
| Programmers] 문자열 내 마음대로 정렬하기 (0) | 2022.11.21 |
