본문 바로가기
Algorithm

[JAVA] [알고리즘 문제] 버전 비교하는 프로그램 / 내 풀이, 다른 풀이 비교

by wanggoNya 2022. 4. 5.

문제

버전 1과 버전 2의 두 버전 번호가 주어지면 비교합니다.

버전 번호는 점 '.'으로 결합된 하나 이상의 구분된 형태로 구성됩니다.

각각의 구분된 형태는 숫자로 구성되며 선행 0을 포함할 수 있습니다.

버전 번호를 비교하려면 수정 버전을 왼쪽에서 오른쪽으로 순서대로 비교합니다.

선행 0을 무시한 정수 값을 사용하여 비교됩니다.

이것은 1과 001이 동일하다고 간주됨을 의미합니다.

버전 번호가 인덱스에서 구분된 형태로 지정하지 않으면 형태를 0으로 처리하십시오.

예를 들어 버전 1.0은 버전 1.1보다 작지만 버전 0과 버전 1은 0 < 1입니다.

 

출력 조건

- 만약 버전 1 < 버전 2, -1을 출력

- 만약 버전 1 > 버전 2, 1을 출력

- 나머지 경우는 0을 출력

 

예 1

입력 : version1 = “1.01”, version 2 = “1.001”

출력 : 0

 

예 2

입력 : version1 = “1.0”, version2 = “1.0.0”

출력 : 0

 

예 3

입력 : version1 = “0.1”, version2 = “1.1”

출력 : -1

 

예 4

입력 : version1 = “1.0.1”, version2 = “1”

출력 : 1


풀이 #1 

reference :  내 깃허브.. ^^  

package day23_HW25;
import java.util.*;
public class Question {
public static void main(String[] args) {
	Scanner sc = new Scanner(System.in);

	// Solution class 호출
	Solution solution = new Solution();

	// 사용자에게 버전 두 개 입력받음
	System.out.print("version1 = ");
	String v1 = sc.next();
	System.out.print("version2 = ");
	String v2 = sc.next();

	// 객체 호출해서 결과 프린트
	System.out.println(solution.version(v1, v2));
}
}

// 버전 비교하는 클래스
class Solution {
	// 사용자에게 입력받은 두 개의 버전을 입력값으로 가진다
	// 비교해서 0 또는 1 또는 -1을 return 한다.
	int version(String v1, String v2) {
		// 사용자에게 입력받은 v1과 v2를 split한다. array가 생성 되었으므로 Arrays.asList를 이용해
		// 새롭게 생성한 ArrayList에 바로 집어 넣어버린다.
		ArrayList<String> v1_list = new ArrayList<String>(Arrays.asList(v1.split("\\.")));
		ArrayList<String> v2_list = new ArrayList<String>(Arrays.asList(v2.split("\\.")));
		
		int output = 0; // 결과 값을 초기화 한다
		int size; // 두 버전을 비교하기 위해 for문을 돌리기 위해 size를 선언한다.
		
		// v1의 사이즈가 더 크면 for문은 v2.size()를 기준으로 돌린다.
		// v2의 사이즈가 더 크면 for문은 v1.size()를 기준으로 돌린다.
		if( v1_list.size() > v2_list.size()) {
			size = v2_list.size();
		} else {
			size = v1_list.size();
		}
		
		// for문을 실행해서 두 버전을 비교한다.
		for(int i = 0; i < size ; i++ ) {
			// 인덱스 0번부터 꺼낸다. 정수로 바꿔주는 과정을 거친다.
			int v1_num = Integer.parseInt(v1_list.get(i));
			int v2_num = Integer.parseInt(v2_list.get(i));
			
			// 두 숫자가 비교 가능하면 바로 1 또는 -1을 return하고 for문을 종료한다.
			if (v1_num > v2_num) {
				output = 1;
				break;
			}else if (v1_num < v2_num) {
				output = -1;
				break;
			// 대소 비교가 가능하면 바로 종료 !
				
			// for문을 다 돌렸는데도 두 버전의 값이 계속 같으면
			// size가 더 큰 버전에서, for문에서 확인하지 못한 뒤쪽 값들 중 0 이상인 것이 있는지 확인한다.
			}else if (v1_num == v2_num) {
				if( v1_list.size() > v2_list.size()) { // v1의 사이즈가 더 크면
					// v1 의 i+1번 인덱스부터 for문을 돌려서
					for(int j = i+1 ; j < v1_list.size() ; j ++) { 
						// 0 이상이면 바로 1을 return
						if (Integer.parseInt(v1_list.get(j)) > 0) output = 1;
					}
				} else if( v1_list.size() < v2_list.size()){ // v2의 사이즈가 더 크면
					// v2 의 i+1번 인덱스부터 for문을 돌려서
					for(int j = i+1 ; j < v2_list.size() ; j ++) {
						// 0 이상이면 바로 -1을 return
						if (Integer.parseInt(v2_list.get(j)) > 0) output = -1;
					}
				}
			// 위에서 1 또는 -1인 경우를 다 걸러주었으므로 나머지는 모조리 0으로 return
			}else {
				output = 0;
			}
		}
		// 위에서 정해진 output 리턴!!!
		return output;
	}
}

주목해야 할 포인트 

1. v1을 split 하여 array를 만듦과 동시에, 바로 Arrays.asList를 이용하여 ArrayList에 저장

 

2. v1과 v2 중 더 작은 size를 기준으로 for문을 돌렸는데도, 여전히 둘의 version이 같다면? 

ex) 1.0과 1.0.00을 비교하려면?

이 경우, if문 내부에서 큰 size의 version list를 for문으로 돌려서, 0 이상의 값이 있는지 확인

 

내 풀이의 특징 및 단점

- 일일이 다 비교함. 모든 경우를 if문과 for문을 이용해 비교하여 코드가 복잡

- 어딘가.... 펑크가 있을 것 같은 느낌적인 느낌


풀이 #2

reference : Park5957 님의 깃허브!!! 감사합니다....

public class test_trining23 {

	public static void main(String[] args) {
//		조건
//		1. 버전1과 버전2 번호의 비교
//		2. 버전의 번호는 "." 으로 결합된 형태
//		3. 버전 1은 001과 동일함
//		4. 예시 버전 1.0 은 버전 1.1 보다 작지만
//			버전 0과 버전 1은 0<1 이다.
//		5. 예시 2
//		버전1<버전2 라면 -1   
//		버전1>버전2 라면 1
//		나머지 경우는 모두 0

//		구성 & 이해
//		1. 1이라도 더 높은쪽이 높다.
//		2. 같다면 소수점 이라도 비교한다.
//		3. 다만 점 이하의 수치의 비교는 상수의 값이 동일할 때만 비교하면 된다.
//		   
		Scanner sc = new Scanner(System.in);
		System.out.print("버전1의 의 값을 입력하시 바랍니다. : ");
		String n = sc.next();
		System.out.print("버전2 의 값을 입력하시 바랍니다. : ");
		String m = sc.next();

		ArrayList<Integer> narry = new ArrayList<>(); // 버전1 저장할 리스트
		ArrayList<Integer> marry = new ArrayList<>(); // 버전2 저장할 리스트

		String[] nSplit = n.split("\\."); // 버전1 "." 기준으로 스플릿 \\는 "." 이 기본키 이기 때문

		for (int i = 0; i < nSplit.length; i++) {

			narry.add(Integer.parseInt(nSplit[i])); // 버전 1 어레이 리스트 보관
		}

		
		
		String[] mSplit = m.split("\\."); // 버전2 "." 기준으로 스플릿 \\는 "." 이 기본키 이기 때문

		for (int i = 0; i < mSplit.length; i++) {

			marry.add(Integer.parseInt(mSplit[i])); // 버전2 어레이 리스트 보관
		}

		if (narry.size() > marry.size()) {  // 버전 1과 버전 2의 길이를 비교 짧은 쪽에 0을 추가 (사족 : 1과 001은 같기에 배열 길이를 맞추기위함)
			int difference = narry.size() - marry.size();
			for (int i = 0; i < difference; i++) {
				marry.add(i, 0); // narry더 길기 때문에  marry의 앞에서 부터 0을 추가

			}
		} else if (narry.size() < marry.size()) {
			int difference = narry.size() - marry.size();
			for (int i = 0; i < difference; i++) {
				narry.add(i, 0);

			}
		}

		int result = 0; //결과 카운트

		for (int i = 0; i < narry.size(); i++) { //narry와 marry의 배열 순차적으로 비교
			if (narry.get(i) == 0 && marry.get(i) == 0) {
				continue;

			} else if (narry.get(i) > marry.get(i)) {
				result = 1;
				break;

			} else if (narry.get(i) < marry.get(i)) {
				result = -1;
				break;
			}
		}

		System.out.println(result); //결과 출력

주목해야 할 포인트 및 장점

1. 둘의 배열 길이가 다르다면, 더 짧은 쪽의 배열 뒤에 0을 add 해버림

 

2. 다시 말해 사용자가 얼마를 입력하건, 어떤 크기의 array가 들어오던, 두 ArrayList의 size를 맞추어버림

 

3. 문제에서 "두 ArrayList의 size가 다를 경우, 어떻게 해결할 것인가"에 포인트를 잘 맞추어 풀이함

 

4. 일일이 비교한 나와 달리, for문이 훨씬 간단해짐

 

5. 마지막 for문에서, 두 배열 모두 0이라면 continue를 사용하여 다음 인덱스로 패스

 

size 맞춘 것도 맞춘 거지만, continue를 써서 0을 패스했다는 게 중요한 듯.

나같은 경우 remove를 써서 0을 삭제하려고도 했음.

while(list.contains("0") 이 난리 했음....

이마를 탁 치고 갑니다


다른 사람 코드 분석의 중요성을

다시 한 번 깨닫고 갑니다.