문제

수를 처리하는 것은 통계학에서 상당히 중요한 일이다. 통계학에서 N개의 수를 대표하는 기본 통계값에는 다음과 같은 것들이 있다. 단, N은 홀수라고 가정하자.

  1. 산술평균 : N개의 수들의 합을 N으로 나눈 값
  2. 중앙값 : N개의 수들을 증가하는 순서로 나열했을 경우 그 중앙에 위치하는 값
  3. 최빈값 : N개의 수들 중 가장 많이 나타나는 값
  4. 범위 : N개의 수들 중 최댓값과 최솟값의 차이

N개의 수가 주어졌을 때, 네 가지 기본 통계값을 구하는 프로그램을 작성하시오.

입력

첫째 줄에 수의 개수 N(1 ≤ N ≤ 500,000)이 주어진다. 단, N은 홀수이다. 그 다음 N개의 줄에는 정수들이 주어진다. 입력되는 정수의 절댓값은 4,000을 넘지 않는다.

출력

첫째 줄에는 산술평균을 출력한다. 소수점 이하 첫째 자리에서 반올림한 값을 출력한다.

둘째 줄에는 중앙값을 출력한다.

셋째 줄에는 최빈값을 출력한다. 여러 개 있을 때에는 최빈값 중 두 번째로 작은 값을 출력한다.

넷째 줄에는 범위를 출력한다.

예제 입력 1

5

1

3

8

-2

2

예제 출력 1

2

2

1

10

 

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

public class Main {
	public static void main(String[] args) throws IOException {
		
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int cnt = Integer.parseInt(br.readLine());

        ArrayList<Integer> numList = new ArrayList<>();
        			     
	    for(int i=0;i<cnt;i++)
		{
			numList.add(Integer.parseInt(br.readLine()));
		}
	    br.close();

        //오름 차순 정렬 미리하기
        Collections.sort(numList);

        /*1. 산술평균 : N개의 수들의 합을 N으로 나눈 값 */
        double res1=0;
        int sum=numList.stream().mapToInt(Integer::intValue).sum();
        res1=Math.round((double)sum/(double)cnt);
       
        /*2. 중앙값 : N개의 수들을 증가하는 순서로 나열했을 경우 그 중앙에 위치하는 값*/
        int res2=Integer.parseInt(numList.get(cnt/2).toString());
        int num [] = numList.stream().mapToInt(Integer::intValue).toArray();

        /*3. 최빈값 : N개의 수들 중 가장 많이 나타나는 값*/
        int res3=0;
        int min2[][]  = new int[cnt][2];   

        for(int i=0;i<cnt;i++)
		{
			min2[i][0]=num[i];
		}

        int tmp=0;
        int temp[] = new int[cnt+1];
        for (int i=0;i<cnt;i++)
        {
            if(cnt==1)
            {
                temp[i]=min2[i][0];
                break;
            }
            for(int j=1;j<cnt;j++)
            {
                if(min2[i][0]==min2[j][0])
                {
                    //빈도수 누적
                    min2[i][1]+=1;
                    //최대 빈도수를 tmp에 저장                    
                    tmp=Math.max(min2[i][1],min2[j][1]);       
                    if(tmp==min2[i][1])
                    {
                        temp[i]=min2[i][0];
                    }             
                }                
            }
        }

        //중복 제거  set 사용 set에서는 중복된 값을 저장할 수 없음
        Set<Integer> set = new HashSet<>();
        for(int loop : temp)
        {
            set.add(loop);
        }
        List numlist = new ArrayList<>(set);
        Collections.sort(numlist);
        
        res3=Integer.parseInt(numlist.get(1).toString());

        /*4. 범위 : N개의 수들 중 최댓값과 최솟값의 차이*/
        int res4=num[cnt-1]-num[0];

        System.out.println((int)res1);	           
        System.out.println(res2);	           
        System.out.println(res3);	           
		System.out.println(res4);	           
	}
}

결과는 시간 초과.... 실패한 코드이다.. 지금 드는 생각은 백준 초반에는 이중 for문을 대충 써서 통과했었는데,

지금은 이중 for문을 쓰면 바로 시간초과의 늪에 걸리는것 같다.

for문을 최소화하고 기존에 선언했던, 배열이나 자료구조형 등을 계속 활용해서 쓰는 방법으로 코드를 짜야할 것 같다.

 

3. 최빈값에서  2차원 배열을 계속 선언하고 temp성으로도 선언해서 쓰고.. 잘 생각해보면 굳이 한번더 새롭게 선언안하고도 활용할 수 있을 것 같은데.. 일단은 2차원 배열 보다는 MAP으로 바꿔서 다시 도전해볼 생각이다.

'IT > Programing' 카테고리의 다른 글

[백준/Baekjoon/java] Q1436 영화감독 숌  (0) 2021.05.17
[백준/Baekjoon/java] Q2798 블랙잭  (0) 2021.05.14

문제

666은 종말을 나타내는 숫자라고 한다. 따라서, 많은 블록버스터 영화에서는 666이 들어간 제목을 많이 사용한다. 영화감독 숌은 세상의 종말 이라는 시리즈 영화의 감독이다. 조지 루카스는 스타워즈를 만들 때, 스타워즈 1, 스타워즈 2, 스타워즈 3, 스타워즈 4, 스타워즈 5, 스타워즈 6과 같이 이름을 지었고, 피터 잭슨은 반지의 제왕을 만들 때, 반지의 제왕 1, 반지의 제왕 2, 반지의 제왕 3과 같이 영화 제목을 지었다.

하지만 숌은 자신이 조지 루카스와 피터 잭슨을 뛰어넘는다는 것을 보여주기 위해서 영화 제목을 좀 다르게 만들기로 했다.

종말의 숫자란 어떤 수에 6이 적어도 3개이상 연속으로 들어가는 수를 말한다. 제일 작은 종말의 숫자는 666이고, 그 다음으로 큰 수는 1666, 2666, 3666, .... 과 같다.

따라서, 숌은 첫 번째 영화의 제목은 세상의 종말 666, 두 번째 영화의 제목은 세상의 종말 1666 이렇게 이름을 지을 것이다. 일반화해서 생각하면, N번째 영화의 제목은 세상의 종말 (N번째로 작은 종말의 숫자) 와 같다.

숌이 만든 N번째 영화의 제목에 들어간 숫자를 출력하는 프로그램을 작성하시오. 숌은 이 시리즈를 항상 차례대로 만들고, 다른 영화는 만들지 않는다.

입력

첫째 줄에 숫자 N이 주어진다. N은 10,000보다 작거나 같은 자연수이다.

출력

첫째 줄에 N번째 영화의 제목에 들어간 수를 출력한다.

예제 입력

2

예제 출력

1666

 

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

public class Main {
	public static void main(String[] args) throws IOException {
		Scanner sc = new Scanner(System.in);
        int cnt = sc.nextInt();
        sc.close();

        String[] mv = new String[cnt];             
        
        int j=0;
        for(int i=666;;i++)
        {
            String to=Integer.toString(i);
            if(to.contains("666"))
            {
                mv[j]=to;
                j++;
                if(j==cnt)
                {
                    break;
                }
            }
        }
        System.out.println(mv[cnt-1]);	    
	}
}

while문도 상관없음. 처음에 문제를 잘못이해해서 검색하는 숫자의 범위가 1~10,000 이라고 생각해버리는바람에 for문으로 작성함.

 

String으로 666을 체크해서 배열에 저장한 다음, 저장된 배열에서 최대값을 출력해준다.

그리고 처음 제출시에는 for문에서도 i를 0으로 초기화해서 사용했었는데, 불필요함.

어차피 최소 666부터 카운트하기때문에 굳이 검사할 필요가 없었음. (0~665)

'IT > Programing' 카테고리의 다른 글

[백준/Baekjoon/java] Q2108 통계학  (0) 2021.05.21
[백준/Baekjoon/java] Q2798 블랙잭  (0) 2021.05.14

블랙잭 

한국어   

카지노에서 제일 인기 있는 게임 블랙잭의 규칙은 상당히 쉽다. 카드의 합이 21을 넘지 않는 한도 내에서, 카드의 합을 최대한 크게 만드는 게임이다. 블랙잭은 카지노마다 다양한 규정이 있다.

한국 최고의 블랙잭 고수 김정인은 새로운 블랙잭 규칙을 만들어 상근, 창영이와 게임하려고 한다.

김정인 버전의 블랙잭에서 각 카드에는 양의 정수가 쓰여 있다. 그 다음, 딜러는 N장의 카드를 모두 숫자가 보이도록 바닥에 놓는다. 그런 후에 딜러는 숫자 M을 크게 외친다.

이제 플레이어는 제한된 시간 안에 N장의 카드 중에서 3장의 카드를 골라야 한다. 블랙잭 변형 게임이기 때문에, 플레이어가 고른 카드의 합은 M을 넘지 않으면서 M과 최대한 가깝게 만들어야 한다.

N장의 카드에 써져 있는 숫자가 주어졌을 때, M을 넘지 않으면서 M에 최대한 가까운 카드 3장의 합을 구해 출력하시오.

입력

첫째 줄에 카드의 개수 N(3 ≤ N ≤ 100)과 M(10 ≤ M ≤ 300,000)이 주어진다. 둘째 줄에는 카드에 쓰여 있는 수가 주어지며, 이 값은 100,000을 넘지 않는 양의 정수이다.

합이 M을 넘지 않는 카드 3장을 찾을 수 있는 경우만 입력으로 주어진다.

출력

첫째 줄에 M을 넘지 않으면서 M에 최대한 가까운 카드 3장의 합을 출력한다.

 

예제 입력 1

5 21

5 6 7 8 9

 

예제 출력 1 

21

 

<제출 코드> -java

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

public class Main {
	public static void main(String[] args) throws IOException {
		
        //입력값 받기
        Scanner sc = new Scanner(System.in);
        //카드 개수
        int cnt = sc.nextInt();
        //총 합
        int max = sc.nextInt();
		
        /*사용자에게 입력받은 카드값 개수를 배열로 선언
        Integer형 배열로 선언한 이유는 처음에 sort 함수를 사용하려고 Integer 배열로 선언함.
        Collections.revserseOrder();
        int 형은 해당 sort method를 쓸 수 없었음..
        하지만 짜다보니 sort method 를 안쓰게되었고,, 바꾸기 귀찮아서 그냥 Integer형 그대로 씀 */        
        Integer[] crd = new Integer[cnt];
		
        //카드3장의 합을 저장할 배열 선언
        int[] top3 = new int[3];		
        
        //카드의 숫자 입력받고 배열에 저장
        for(int i=0;i<cnt;i++)
        {
        	crd[i]=sc.nextInt();
        }
        sc.close(); //닫아주기
	       	    
// 3중 for문으로 배열에 저장한 카드의 3쌍 조합을 모두 구하기       
Loop1:  for (int i=0;i<cnt;i++)
	    {    	
	    	for(int j=i+1;j<cnt;j++)
	    	{
	    		for(int k=j+1;k<cnt;k++)
	    		{
                    //tmp에 임시로 저장하고
	    			int tmp=crd[i]+crd[j]+crd[k];	    		
                    
                    /*tmp가 사용자가 입력한 최대값보다 작은지 확인,
                    top3는 모두0으로 초기화 되어있기때문에 (int형배열이라)
                    tmp값을 계속 비교해서 제일 큰값만 저장하도록 &&로 체크 */      
	    			if (tmp<max && tmp>=top3[0])
	    			{
	    				top3[0]=tmp;
	    			}
	    			else if (tmp==max)
	    			{
	    				top3[0]=tmp;
	    				break Loop1; //카드의 합이 입력받은 최대값과 동일하다면 for문을 바로 종료
	    			}
	    		}
	    	}
	    }	   
        // 위의 if문에서 최대값만을 top3[0]에 저장하므로, top3[0] 만 출력
	   System.out.println(top3[0]);	    
	}
}

<제출 결과>

 

우선 결과는 위와 같았다.  제출 이후 메모리랑 수행시간을 다른사람과 비교해서 살펴보니,

입력 받을때 BufferedReader 도 쓰고 여러가지 쓰던데.. java가 오랜만이라 java 입력으로 검색해서 바로 나오는 Scanner 썼다.

좀 더 익숙해지면 메모리랑 수행시간도 생각해서 제출할 수 있도록 해야겠다.

'IT > Programing' 카테고리의 다른 글

[백준/Baekjoon/java] Q2108 통계학  (0) 2021.05.21
[백준/Baekjoon/java] Q1436 영화감독 숌  (0) 2021.05.17

+ Recent posts