디지털 액자 개선

출장기간 남는 시간을 보내기 위해, 전에 만들던 디지털 액자를 다시 손보기로 했다. 전에 제작한 프로그램은 다음 문제점을 가지고 있다.

  1. 서버가 저장한 파일 이름을 받을 수 없음.
  2. 간혹 200개 중 몇 개 빼먹고 다운로드.
  3. 앱이 하루 중 특정 시각 파일을 받기 때문에, 앱이 정지되면 다음날까지 기다려야 함.

1, 2 번을 수정했고 3번도 할 수 있으나 너무 많이 뜯어 고쳐야 하므로 안했다. socket을 열어 단순 파일만 받았으나, text를 전송하여 1. 전체 파일 개수 전송, 2. i번째 파일 이름, 크기 전송, 3. i번째 파일 내용 전송으로 바꿨다. 이 socket을 이용하여 앱에 특정 버튼을 만들어 서버에서 파일을 업데이트, 전송하게 할 수 있다. 대략 아래와 같이 구성했다.

socket 으로 파일을 보낸 후 다음에 다시 쓰기위해 close 안했다. 이렇게 하면 받는 쪽이 얼마나 받을지 모르기 때문에, 크기를 전송했다.

https://stackoverflow.com/questions/4886293/socket-input-stream-hangs-on-final-read-best-way-to-handle-this

파일 전송 후, 바로 텍스트를 보내면 40개 정도 파일을 보내고 한없이 기다린다. 이 경우 다시 무엇인가 전송하도록 해줘야 하는데, 귀찮고 어려워 그냥 딜레이를 썼다. 이 물건을 더 뜯어 고치고 싶진 않다. 담엔 무엇을 해야 하나?

서버 코드

package sender;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {
	public static void main(String[] args) {

		ServerSocket serverSocket = null;
//		final String FILE_TO_SEND = "/home/now0930/tempPhoto/1234.jpg";
//		byte[] myFileByteArray;
		FileInputStream fis;
		BufferedInputStream bis;
//		File myFileToSend;
		File myPhotoDirectory;
		File[] myFiles;
//		int i = 0;
		String responderStr;
		int action = 0;
		final int DEFAULT_BUFFER_SIZE = 1000000;

		boolean myDirectoryWasUpdated = false;
		boolean ended = false;
		int fileIndex = 0;
		/*
		 * try { serverSocket = new ServerSocket(9998); System.out.println(getTime() +
		 * "서버가 준비되었음.");
		 * 
		 * } // try catch (IOException e) { e.printStackTrace(); } // catch
		 */

		// myFileToSend = new File(FILE_TO_SEND);
		// myFileByteArray = new byte[(int)myFileToSend.length()];

//		while (true) {
		// 서버에서 실행 방법..
		// script 실행 분.
		// 서버가 특정 디렉토리에 특정 시각에 jpg file을 교체, 기존 파일을 삭제
		// 종료 후, updated란 파일을 만듦.
		// 특정 시각에 cron이 실행

		// java 실행 분..
		// 디렉토리에서 updated를 찾음..
		// updated란 파일을 찾으면,
		// socket.accept()로 일정시간 기다린 후,
		// 응답.
		// 파일 1회 전송후 process 종료.
		// updated 파일 삭제

		// updated 파일이 없으면
		// 프로세스 종료..

		// file 입출력..
		// 디렉토리의 파일을 리스트로 만드는 부분.
		// directory의 파일 찾기

		myPhotoDirectory = new File("/home/now0930/tempPhoto");
		myFiles = myPhotoDirectory.listFiles();
		System.out.println("출력" + myFiles.length);

		myDirectoryWasUpdated = false;
		// updated 파일 확인..
		for (int j = 0; j < myFiles.length; j++) {
			if (myFiles[j].getName().equals("updated")) {
				myDirectoryWasUpdated = true;
				System.out.println("파일이 업데이트 되었음");
				break;
			}
		} // for

		// 파일이 업데이트 되지 않으면, while를 빠져 나감..
		if (myDirectoryWasUpdated) {

			try {
				serverSocket = new ServerSocket(9998);
				System.out.println(getTime() + "서버가 준비되었음.");
				Socket socket = serverSocket.accept();
				System.out.println(getTime() + socket.getInetAddress() + "로부터 연결이 들어옮");
				InputStreamReader responder = new InputStreamReader(socket.getInputStream());
				BufferedReader bfResponder = new BufferedReader(responder);
				OutputStream out = socket.getOutputStream();
				PrintWriter responderToClient = new PrintWriter(socket.getOutputStream());
				String[] temp;
				// 폴더의 파일 리스트 전송
				System.out.println(getTime() + "서버가 대기중");
				while (true) {
					responderStr = bfResponder.readLine();
					System.out.println(responderStr);
					Pattern patFilename = Pattern.compile("send [0-9]{1,3} filename");
					Pattern patFileContents = Pattern.compile("send [0-9]{1,3} filecontents");
					Pattern patClose = Pattern.compile("close");
					Matcher matFilename = patFilename.matcher(responderStr);
					Matcher matFileContents = patFileContents.matcher(responderStr);
					Matcher matClose = patClose.matcher(responderStr);
					if (responderStr.equals("how many files has you?")) {
						action = 1;
					} else if (matFilename.find()) {
						// 파일 인덱스를 세부 판단.
						temp = responderStr.split(" ");
						fileIndex = Integer.parseInt(temp[1]);
						// action 4: client에 END를 보내고 소켓 닫음.
						// updated를 지움
						// action 2: client로 파일을 보냄.
						action = (fileIndex >= myFiles.length) ? 4 : 2;

					} else if (matFileContents.find()) {
						action = 3;
					} // match fileContents

					switch (action) {
					// 1: how many files have you?
					case 1:
						responderToClient.println("FileList: " + myFiles.length);
						responderToClient.flush();
						System.out.println("파일 갯수 보냄.");
						break;
					// send ??? filename
					case 2:
						System.out.println("정규식 감지됨");
//						temp = responderStr.split(" ");
//						fileIndex = Integer.parseInt(temp[1]);

						// updated 파일을 보내지 않고, 그림 파일만 보냄.
						// 파일 이름과 크기를 보냄.
						// 크기를 보내야 받는쪽에서 얼마나 받을지 앎. 이후 판단.
						if (myFiles[fileIndex].getName().contains("jpg") || myFiles[fileIndex].getName().contains("png")
								|| myFiles[fileIndex].getName().contains("JPEG")
								|| myFiles[fileIndex].getName().contains("JPG")) {
							responderToClient.println("Filename: " + myFiles[fileIndex].getName() + ", FileSize: "
									+ myFiles[fileIndex].length());
							System.out.println("Filename: " + myFiles[fileIndex].getName() + ", FileSize: "
									+ myFiles[fileIndex].length());
							responderToClient.flush();
						} else {
							responderToClient.println("Filename: this is no image file");
							responderToClient.flush();
						}
						break;
					// send ??? filecontents
					case 3:
						/*
						 * if (fileIndex >= myFiles.length) myFileByteArray = null; else myFileByteArray
						 * = new byte[(int) myFiles[fileIndex].length()];
						 */
						// fis = new FileInputStream(myFileToSend);
						// myFiles.length 가 0일 경우, myFiles[i]가 arrayOutOfBoundsException이 있음..

						/**
						 * if(myFiles.length !=0 && myFiles[i].exists()&& //updated란 파일을 안보내게 제외..
						 * myFiles[i].getName()!="updated" && //확장자가 jpg만 보냄..
						 * myFiles[i].getName().matches(".*\\.jpg")){
						 **/
						int readBytes;
						byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
						fis = new FileInputStream(myFiles[fileIndex].getPath());
						bis = new BufferedInputStream(fis);
						// bis.read(myFileByteArray,0,myFileByteArray.length);
						// bis.read(myFileByteArray, 0, myFileByteArray.length);
						while ((readBytes = fis.read(buffer)) > 0) {
							out.write(buffer, 0, readBytes);
							out.flush();
						}
						System.out.println(getTime() + myFiles[fileIndex].getPath() + "를 보냅니다.");
						System.out.println(fileIndex + "번째 파일 전송 완료.");
						// out, socket을 계속 사용하기 위해 닫지 않음.
						break;

					case 4:
						// 보낼 파일을 가지고 있는지 확인.
						// 마지막 파일이면 client로 END를 보내고 updated 파일 삭제.
						if (fileIndex >= myFiles.length) {
							responderToClient.println("End");
							responderToClient.flush();
							// App으로 END를 보내고 updated 파일 삭제.
							ended = true;
							// 파일 삭제 확인..
							// j값을 기억하고 있다, 나중에 삭제..
							for (int j = 0; j < myFiles.length; j++) {
								if (myFiles[j].getName().equals("updated")) {
									myDirectoryWasUpdated = false;
									myFiles[j].delete();
									System.out.println("파일이 삭제되었음");
									break;
								} // if
							} // for

						} // if fileIndex..
						// switch, case break;
						break;

					}// switch
					//switch문 실행시 다시 readline을 하지 않기 위해, 여기에서 강제 브레이크
					if (ended) {
						// close socket
						socket.close();
						System.out.println("Socket 닫힘");
						// while break
						break;
					}
				} // while

			} // try
			catch (IOException e) {
				e.printStackTrace();
			} // catch

			catch (Exception e) {
				e.printStackTrace();

			} // catch

		} // if myDirectory is updated?

	}// main

	private static String getTime() {
		// TODO Auto-generated method stub
		SimpleDateFormat f = new SimpleDateFormat("[hh:mm:ss]");
		return f.format(new Date());
	}// getTime

}

클라이언트 코드(안드로이드 앱, Receiver 클래스)

package tk.now0930.photoframev2;

import android.content.Context;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ConnectException;
import java.net.Socket;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by now0930 on 17. 9. 23.
 */

public class LongTermTaskReceive {
    Timer myScheduler;
    TimerTask mLongTermTaskReceive;
    Calendar currentTime;
    public static final int ServerPort = 9999;
    String FileToReceive;
    byte[] myByteArray;
    File file;
    FileOutputStream fos;
    BufferedOutputStream bos;
    int bytesRead;
    int current = 0;
    private static int fileIndex = 0;
    long passedCheck, displayCheck;
    Context myContext;
    static int state = 0;

    LongTermTaskReceive(Context from) {
        this.myContext = from;
        currentTime = ((PhotoFrame) myContext).getCalendar().getInstance();
        myScheduler = ((PhotoFrame) myContext).getTimerRecive();
        fos = null;
        bos = null;

        mLongTermTaskReceive = new TimerTask() {
            @Override
            public void run() {
                //매 턴 시각을 받기위해, run안에도 설정.
                currentTime = ((PhotoFrame) myContext).getCalendar().getInstance();
                //passedCheck>0 이면 지정 시각이 지났음..
                passedCheck = currentTime.getTimeInMillis() - Constants.mReceiveTimeStop.getTimeInMillis();
                //display할 시간인 지 확인..
                //app이 충돌함..
                displayCheck = currentTime.getTimeInMillis() - Constants.mShorttermTimeStart.getTimeInMillis();

                if (displayCheck < 0) {
                    try {
                        String ServerIP = "192.168.1.73";
                        System.out.println("S:Connecting");
                        Socket socket = new Socket(ServerIP, 9998);
                        //파일 이름, 요청하기 위해 연결 설정.
                        PrintWriter askToServer = new PrintWriter(socket.getOutputStream());
                        InputStream in = socket.getInputStream();
                        String deciderStr;
                        InputStreamReader decieder = new InputStreamReader(socket.getInputStream());
                        BufferedReader bfDecieder = new BufferedReader(decieder);
                        //정규표현식을 사용하기 위해 Matcher, Pattern 설정.
                        String[] fileToAccept;
                        String fileNameTmp = "";
                        String fileSizeTmp = "";
                        int fileIndex = 0;
                        int i = 0;
                        while (true) {
                            switch (state) {
                                //처음 파일 갯수요청
                                //보냈을 때 바로 readline 실행.
                                //같이 실행하지 않으면 한없이 기다릴 수 있음.

                                case 0:
                                    askToServer.println("how many files has you?");
                                    askToServer.flush();
                                    deciderStr = bfDecieder.readLine();
                                    Pattern patFilelist = Pattern.compile("FileList: ");
                                    Matcher matFilelist = patFilelist.matcher(deciderStr);
                                    if (matFilelist.find()) {
                                        fileToAccept = deciderStr.split(" ");
                                        fileIndex = Integer.parseInt(fileToAccept[1]);
                                        state = 1;
                                    }
                                    //파일 갯수 수신 대기
                                    // 서버가 전송한 메세지를 분석하는 부분..
                                    //다음에 어느 스테이트로 갈지 결정.
                                    //여기로 들어오면 항상 기다릴 수 있음.
                                    //전 스텝에서 메세지를 하나 보내야 됨.
                                    //여기로 들어오면 일단 다른 case로 나감.
                                    //i번째 파일 이름 요청, 받은 후 i 증가.
                                    break;
                                case 1:
                                    askToServer.println("send " + i + " filename");
                                    askToServer.flush();
                                    deciderStr = bfDecieder.readLine();
                                    Pattern patFilename = Pattern.compile("Filename:( .*.(jpg|png|JPG|JPEG)), FileSize: ([0-9]{0,10})");
                                    Matcher matFilename = patFilename.matcher(deciderStr);
                                    Pattern patEnd = Pattern.compile("End");
                                    Matcher matEnd = patEnd.matcher(deciderStr);
                                    if (matFilename.find()) {
                                        fileNameTmp = matFilename.group(1);
                                        fileSizeTmp = matFilename.group(3);
                                        //fileSizeTmp 크기 버퍼를 만듦.
                                        //socket에서 오는 입력을 버퍼로 써주고, 마지막까지 읽으면 파일로 써줌.
                                        myByteArray = new byte[Integer.parseInt(fileSizeTmp)];
                                        System.out.println("filename is: " + fileNameTmp);
                                        System.out.println("filesize is: " + fileSizeTmp);
                                        state = 2;
                                    } else if (matEnd.find()) {
                                        state = 5;
                                        break;
                                    } else {
                                        i++;
                                        state = 1;
                                    }
                                    break;
                                //이미 보내진 파일 갯수를 보고 파일 수신.
                                case 2:
                                    //FileToReceive = "receivedFile" + fileIndex + ".jpg";
                                    askToServer.println("send " + i + " filecontents");
                                    askToServer.flush();

                                    file = new File(Constants.FileDirectory, fileNameTmp);
                                    fos = new FileOutputStream(file);
                                    //System.out.println("파일 출력 위치"+((PhotoFrame)myContext).getApplicationContext().getFilesDir());
                                    System.out.println("파일 출력 위치" + file.getAbsoluteFile());
                                    bos = new BufferedOutputStream(fos);
                                    bytesRead = in.read(myByteArray, 0, myByteArray.length);
                                    current = bytesRead;
                                    do {
                                        bytesRead = in.read(myByteArray, current, (myByteArray.length - current));
                                        if (bytesRead >= 0)
                                            current += bytesRead;
                                        //socekt이 끊기면 빠저나감.

                                        if (bytesRead == -1)
                                            break;
                                    } while (myByteArray.length > current);
                                    bos.write(myByteArray, 0, current);
                                    i++;
                                    //다음에 소켓을 사용해야 하므로 끊어주면 안됨
                                    //bos.flush();
                                    //in.close();
                                    //파일을 수신하고 있다고 메세지를 보냄..
                                    ((PhotoFrame) myContext).myHandler.sendEmptyMessage(1);
                                    System.out.println("message..파일 수신.");
                                    state = 1;
                                    //너무 빠르면 socket 전송을 잃어버림.
                                    //서버가 충분하게 읽을 수 있도록 적정 시간 지연.
                                    TimeUnit.SECONDS.sleep(1);
                                    break;

                                //연결 종료.
                                case 5:
                                    System.out.println("연결 종료됨.");
                                    in.close();
                                    //while문을 나가면 처음부터 다시 시작.
                                    //while loop를 유지하여 여기에서 close하고, state 6에서 대기.
                                    state = 6;
                                    break;
                                case 6:
                                    TimeUnit.SECONDS.sleep(10);
                                    break;
                            }//switch

                        } //while


                    }   //try

                    catch (ConnectException e) {
                        e.printStackTrace();
                    } //catch, ConnectException

                    catch (IOException e) {
                        e.printStackTrace();
                    }//catch, IOException

                    catch (Exception e) {
                        e.printStackTrace();
                    }   //catch, Exception

                }//display 시간 확인..

                if (passedCheck > 0) {
                    System.out.println("message...Receive 타이머가 cancel..");
                    ((PhotoFrame) myContext).myTimerThread.setReceiveTimerFlagFLASE();
                    cancel();
                }//if


            }//run
        };//TimerTask
        //특정 시각에 작업 시행..오후 8시 57분..
        myScheduler.schedule(mLongTermTaskReceive, Constants.mReceiveTimeStart.getTime(), TimeUnit.MILLISECONDS.convert(3, TimeUnit.SECONDS));
        System.out.println("ReceiveTime 시각은.." + Constants.mReceiveTimeStart.getTime());
    }//LongTermTaskReceive


}

안드로이드 전체 앱

프로그래머스 예산

정확성은 다 맞는데, 효율성이 떨어진다. 효율성 2번, 3번은 도대체 어떻게 할지 모르겠다. 또한 효율성 통과 기준이 너무 높다. 19ms는 충분히 빠르다. 반드시 이분 탐색으로 풀어야 효율성 테스트를 통과하는 듯 하다. 정확성은 좀 쉬운데, 효율성 테스트가 또 마의 영역이다.

이 문제에서 이분 탐색을 어떻게 활용해야되는지 모르겠다. 너무 많이 진행되어 엎을 수 없어 보완했다.


import java.util.Arrays;

public class Bugdet {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Solution sol = new Solution();
		int[] budgets = { 120, 110, 140, 150 };
		int M = 485;
		int answer = 0;
		answer = sol.solution(budgets, M);
		System.out.println("테스트: " + answer);

	}

}

class Solution {
	public int solution(int[] budgets, int M) {
		//배열을 오름차순 정렬.
		Arrays.sort(budgets);
		/*
		 * for (int i = 0; i < budgets.length; i++) System.out.println(budgets[i]);
		 */
		int t = budgets[budgets.length - 1];
		int k = 0;
		long answer = 0;
		int tempSum = M + 1;
		while (tempSum > M) {
			answer = t;
			tempSum = sum(budgets, k, t);
			k = Arrays.binarySearch(budgets, t);

			if (k < 0)
				k = -(k + 1);
			k = budgets.length - k;
			if (sum(budgets, k + 1, budgets[budgets.length - k - 1]) >=M)
				t = budgets[budgets.length - k - 1];
			else
				t = t - 1;

		} //while
		/*
		 * for (int i = 0; i < budgets.length; i++) { int tempSum = sum(budgets, k, t);
		 * if (tempSum <= M) { answer = t; break; } else { t = t - 1; k =
		 * Arrays.binarySearch(budgets, t); if (k < 0) k = -(k + 1); k = budgets.length
		 * - k; } answer = t; }
		 */
		return (int)answer;
	}

	public int sum(int[] budgets, int k, int t) {
		int tempSum = 0;
		for (int i = 0; i < budgets.length - k; i++) {
			tempSum = tempSum + budgets[i];
		}
		//		for (int j = 0; j < k; j++)
		//			tempSum = tempSum + t;

		tempSum = tempSum + k * t;
		return tempSum;

	}

}

프로그래머스 2xn 타일링

문제를 읽으면 어렵다. 출제자 기준에서 생각한다면, 답이 큰 수임을 보고 수열을 묻는 문제임을 알아야 한다. 이 바닥에서 유명한 피보나치 수열을 묻는 문제라고 눈치채야 한다.

public class Main {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Solution sol = new Solution();
		int n = 0;
		for (int i = 0; i < 100; i++) {
			n = sol.solution(i);
			System.out.println("i는 " + i + ", n은" + n);
		}

	}

}

class Solution {
	public static int solution(int n) {
		int a = 1, b = 2, c = 0;
		if (n == 0)
			return 1;
		else if (n < 2)
			return n;

		for (int i = 2; i < n; i++) {
			c = b;
			b = (a + b) % 1000000007;
			a = c;

		}
		return b;
	}
}

프로그래머스 베스트앨범

내가 너무 어렵게 푸나? 다른 사람 코드는 쉽던데. 이 문제가 java Collection framework를 아는지 물어본다. 물론 난 잘 모르지만.


import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeMap;

public class Main {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		// 시작..
		//		String[] operations = { "I16", "I10", "I20", "D1" };

		String[] genres = { "classic", "pop", "classic", "classic", "pop" };
		int[] plays = new int[] { 500, 600, 150, 800, 2500 };
		Solution sol = new Solution();
		int[] answer = new int[10];
		answer = sol.solution(genres, plays);
		System.out.println("답은"+answer);

	}
}

class Solution {
	public int[] solution(String[] genres, int[] plays) {
		int[] answer;
		TreeMap<String, Integer> genresSelcetion = new TreeMap<>();
		TreeMap<Integer, Integer> genresIndex = new TreeMap<>();
		ArrayList<Integer> bestAlbum = new ArrayList<>();

		for (int i = 0; i < genres.length; i++) {
			int count = 0;
			//			count = genresSelcetion.get(genres[i]);
			if (genresSelcetion.get(genres[i]) == null) {
				//genres가 없음.
				genresSelcetion.put(genres[i], plays[i]);
				//				System.out.println("String은" + genres[i]);
			} else { //genres가 있음.
				count = genresSelcetion.get(genres[i]);
				genresSelcetion.put(genres[i], count + plays[i]);

			}
			System.out.println("카운트" + count);
		}

		//TreeMap 왼쪽 정렬.
		Comparator<String> comparator = new ValueComparator<String, Integer>(genresSelcetion);
		TreeMap<String, Integer> sortedGenresSelection = new TreeMap<>(comparator);
		sortedGenresSelection.putAll(genresSelcetion);
		Iterator<String> itrGenres = sortedGenresSelection.keySet().iterator();

		//입력된 String[] genres - key, 곡 index - value로 만듦.
		while (itrGenres.hasNext()) {
			String key = itrGenres.next();
			System.out.println("Key=" + key);
			for (int i = 0; i < genres.length; i++) {
				if (genres[i].equals(key)) {
					genresIndex.put(i, plays[i]);
					System.out.println("No" + i + " is genres=" + genres[i] + ", plays =" + plays[i]);
					//넣을때 정렬.
				}

				System.out.println("전체 value은" + genresIndex.values());
			} //for
				//한 장르 모두 끝난 후, 값으로 정렬
				//다시 사용하기 위해 loop 안에서 선언
			Comparator<Integer> comparator2 = new ValueComparator<Integer, Integer>(genresIndex){

				@Override
				public int compare(Integer arg0, Integer arg1) {
					// TODO Auto-generated method stub
					return map.get(arg0)> map.get(arg1)?-1:1;

				}
				
				
			};
			TreeMap<Integer, Integer> sortedGenresIndex = new TreeMap<>(comparator2);
			sortedGenresIndex.putAll(genresIndex);
			Iterator<Integer> itrGenresIndex = sortedGenresIndex.keySet().iterator();
			int j = 0;
			while (itrGenresIndex.hasNext()) {
				//정리한 순서를 Array List에 삽입
				Integer playIndex = itrGenresIndex.next();
				j++;
				if (j > 2)
					break;
				bestAlbum.add(playIndex);
			}

			System.out.println("여기 확인!! value은" + sortedGenresIndex.values());
			for (int k = 0; k < bestAlbum.size(); k++)
				System.out.println("여기는 ArrayList" + bestAlbum.get(k));

			//clear TreeMap..
			sortedGenresIndex.clear();
			genresIndex.clear();

		} // while
		/*
		 * while (itrGenres.hasNext()) {
		 * 
		 * Object key = itrGenres.next(); System.out.println("key는" + key);
		 * System.out.println("value는" + sortedGenresSelection.get(key));
		 * 
		 * }
		 * 
		 */
		//		System.out.println("전체 value은" + sortedGenresSelection.values());

		answer = new int[bestAlbum.size()];
		for (int l = 0; l < bestAlbum.size(); l++) {
			answer[l] = bestAlbum.get(l);

		}
		return answer;

	}

}//Solution

class ValueComparator<K, V extends Comparable<V>> implements Comparator<K> {
	TreeMap<K, V> map = new TreeMap<K, V>();

	public ValueComparator(TreeMap<K, V> map) {
		this.map.putAll(map);
	}

	@Override
	public int compare(K arg0, K arg1) {
		// TODO Auto-generated method stub
		return -map.get(arg0).compareTo(map.get(arg1));
	}

} //class ValueComparator

TreeMap Value로 정렬

keyset, entryset 차이

java8 이후로 추가된 treemap 정렬

프로그래머스 이중우선큐

아래처럼하면 될듯하다.

위 방법대로 하려다 잘 안된다. max 큐에서 min큐로 변경될 때 연산이 하나씩 틀어진다. 결국 max queue를 poll하면 min queue를 클리어하고, max queue로 업데이트 했다.


import java.util.Collections;
import java.util.regex.*;
import java.util.PriorityQueue;

public class Main {

	public static void main(String[] args) {
		// 시작..
		//		String[] operations = { "I16", "I10", "I20", "D1" };
		String[] operations = { "I -45", "I 653", "D 1", "I -642", "I 45", "I 97", "D 1", "D -1", "I 333" };

		Solution sol = new Solution();
		int[] t = sol.solution(operations);
		System.out.println(t[0]+","+ t[1]);
	}// void main

}

class Solution {
	public int[] solution(String[] operations) {
		Pattern tmpNumber = Pattern.compile("(-[0-9]{1,}|[0-9]{1,})");
		PriorityQueue<Work> pqMax = new PriorityQueue<>();
		PriorityQueue<Work> pqMin = new PriorityQueue<>(Collections.reverseOrder());


		for (int in = 0; in < operations.length; in++) {
			//			System.out.println("인자: " + operations[in] + operations[in]);
			String op = operations[in].substring(0, 1);
			//정규표현식으로 숫자만 출력.
			Matcher tmpMatcher = tmpNumber.matcher(operations[in]);
			String tmpNum = "";
			Integer num = 0;
			//			int num = Integer.parseInt(tmpMatcher.group());
			while (tmpMatcher.find()) {
				tmpNum = tmpMatcher.group();
				//				System.out.println(tmpMatcher.group());
			}
			num = Integer.parseInt(tmpNum);
			//			System.out.println(num);
			//			System.out.println(tmpMatcher.find());

			//			int num = Integer.parseInt(operations[in + 1]);
			if (op.equals("I")) {

				pqMax.add(new Work(num));
				pqMin.add(new Work(num));

			} else if (op.equals("D"))
				if (num.equals(1)) {
					pqMax.poll();
					if (pqMax.size() == 0)
						//size가 0이면 마지막 1개를 취출했음.
						pqMin.poll();
					else {
						pqMin.clear();
						pqMin.addAll(pqMax);
					}
				} else if (num.equals(-1)) {
					pqMin.poll();
					if (pqMin.size() == 0)
						//size가 0이면 마지막 1개를 취출했음.
						pqMax.poll();
					else {
						pqMax.clear();
						pqMax.addAll(pqMin);
					}

				}

		}

		/*
		 * System.out.println("Max 큐"); while (!pqMax.isEmpty()) {
		 * System.out.println(pqMax.poll().number); }
		 * 
		 * System.out.println("Min 큐"); while (!pqMin.isEmpty()) {
		 * System.out.println(pqMin.poll().number); }
		 */

		int[] answer = new int[2];
		if (pqMax.size() != 0)
			answer[0] = pqMax.poll().number;
		else
			answer[0] = 0;
		if (pqMin.size() != 0)
			answer[1] = pqMin.poll().number;
		else
			answer[1] = 0;

		return answer;
	} //solution

}

class Work implements Comparable<Work> {
	int number;

	Work(Integer num) {
		this.number = num;
	}

	@Override
	public int compareTo(Work arg0) {
		// TODO Auto-generated method stub

		return this.number > arg0.number ? -1 : 1;
	}

}