[출처] 자바의 정석 3판 연습문제 Chapter 11

 

정답)

 

(1)

public int compareTo(Object o) {
	if(o instanceof Student) {
		Student s = (Student)o;
		return (total - s.total)*(-1);
	}
	return -1;
	
}

 

(2) 

	public static void calculateSchoolRank(List list) {
		Collections.sort(list); // 먼저  list를 총점기준 내림차순으로 정렬한다.
		int prevRank = -1; // 이전 전교등수
		int prevTotal = -1; // 이전 총점
		int length = list.size();
		
		for(int i=0; i<length; i++) {
			Student s = (Student)(list.get(i));
			if(s.getTotal() == prevTotal) {
				s.schoolRank = prevRank;
			} else {
				s.schoolRank = i+1;
			}
			
			prevTotal = s.getTotal();
			prevRank = s.schoolRank;
		}

		
	}

 

풀이)

(1)

내림차순으로 정렬해야 하므로 기본정렬 방식에 -1을 곱해주면 된다.

 

(2)

이미 list를 내림차순으로 정렬해 놓았다. 따라서 있는 그대로 등수만 잘 매기면 된다.

 

현재 점수가 이전 점수와 같을때만 이전의 순위를 그대로 갖게 하고(같은 등수를 가진다)

 

총점이 이전 점수와 다르다면, 이전 점수보다 현재 점수가 낮다는 뜻이기 때문에(정렬의 영향) 등수를 1 올리면 되는데,

i값을 이용해서 등수를 i+1로 하게 되면 앞에 동점자가 여러명이 있어도 동점자를 고려한 등수값이 정해지게 된다.

 

 

 

 

 

 

정답)

 

(1)

class ClassTotalComparator implements Comparator { // 반별 총점기준 내림차순 정렬
	public int compare(Object o1, Object o2) {
		if(o1 instanceof Student && o2 instanceof Student) {
			Student s1 = (Student)o1;
			Student s2 = (Student)o2;
			
			if(s1.ban==s2.ban) {
				return s2.total - s1.total;
			} else {
				return s1.ban - s2.ban;
			}
			
		}
		return -1;
	}
}

 

(2)

public class Practice2 {
	public static void calculateClassRank(List list) {
		// 먼저 반별 총점기준 내림차순으로 정렬한다
		Collections.sort(list, new ClassTotalComparator());
		
		int prevBan = -1;
		int prevRank = -1;
		int prevTotal = -1;
		int length = list.size();
		
		for(int i=0, n=0; i<length; i++, n++) {
			Student s = (Student)(list.get(i));
			if (s.ban!=prevBan) {
				prevRank = -1;
				prevTotal = -1;
				n = 0;
			}
			
			if(s.total==prevTotal) {
				s.classRank=prevRank;
			} else {
				s.classRank=n+1;
			}
			
			prevBan = s.ban;
			prevTotal = s.total;
			prevRank = s.classRank;
		}
		
		
		
	}

 

풀이)

 

(1)

반 별로 정렬은 오름차순이므로 일반적인 방법으로 ban의 차이를 이용한다.

총점 기준 내림차순 정렬은 총점의 차이값을 구한 후 1을 곱한 값을 반환값으로 주면 된다.

 

(2)

반이 바뀔 때, 등수를 어떻게 매기는지가 핵심인 문제다.

 

반이 바뀌기 전에는 점수로 정렬된 Student 객체에 매 반복문마다 1씩 증가하는 n을 이용해서 등수를 설정한다.

이미 내림차순으로 정렬을 해놨기 때문에 n+1을 그대로 등수(s.classRank)에 저장하면 된다.

 

점수가 같을때만 이전 등수(prevRank)Student 객체의 등수(s.classRank)에 저장하면 된다.

 

반이 바뀌면 prevTotal, prevRank, n을 초기화 시켜주기만 하면 되는데,

n의 값을 0으로 초기화 시켜주는것만 주의하면 된다. 이것 때문에 i 대신 변수 n을 하나 더 만들어서 사용했다.

 

 

 

정답)

 

import java.util.*;

public class Practice {

	public static void main(String[] args) {
		Set set = new HashSet();
		
		int[][] board = new int[5][5];
		
		for(int i=0; set.size() < 25; i++) {
			set.add((int)(Math.random()*30)+1+"");
		}
		
		ArrayList list = new ArrayList(set);
		Collections.shuffle(list);
		
		Iterator it = list.iterator();
		
		for(int i=0; i < board.length; i++) {
			for(int j=0; j < board[i].length; j++) {
				board[i][j] = Integer.parseInt((String)it.next());
				System.out.print((board[i][j] < 10 ? "  " : " ")
						+ board[i][j]);
			}
			System.out.println();
		}

 	}

}

 

풀이)

 

HashSet이 중복을 허용하지 않고 순서를 유지하지 않기 때문에 발생하는 문제이다.

아무리 임의의 순서로 저장을 해도, 해싱 알고리즘의 특성상 한 숫자가 고정된 위치에 저장되기 때문이다.

 

그래서 저장순서를 유지하는 ArrayList에 HashSet의 데이터를 옮겨 담고

Collections 클래스의 shuffle() 메소드를 이용해서 데이터들의 순서를 섞는 방법을 사용했다.

컬렉션 클래스끼리는 서로 다른 컬렉션으로 데이터를 쉽게 옮길 수 있다. (생성자 매개변수 활용)

 


[출처] 자바의 정석 3판 연습문제 Chapter 11

+ Recent posts