Find Numbers with Even Number of Digits

유길상·2022년 5월 26일
0

자료구조 - 리스트

목록 보기
4/10

문제

전제
Integer객체의 nums배열이 주어졌을때 자리 수가 짝수인 값의 총 개수를 반환합니다.

예제1

Input: nums = [12,345,2,6,7896]
Output: 2
설명:
12는 2자리 수이다.(짝수).
345는 3자리 수이다. (홀수).
2는 1자리 수이다. (홀수).
6은 1자리 수이다. (홀수).
7896은 4자리 수이다. (짝수).
값들 중 오직 12와 7896만 자리 수가 짝수이다

예제2

Input: nums = [555,901,482,1771]
Output: 1
Explanation:
오직 1771만 짝수 자리 수의 숫자이다.

제약 조건

1 <= nums.length <= 500
1 <= nums[i] <= 1000000


Solution

나의 풀이

class Solution {
    public int findNumbers(int[] nums) {
		int cntEvenNumberOfDigits = 0; //짝수 자리 수의 숫자 카운트
		
        //i가 nums의 길이보다 크지 않을 때 까지 반복한다
		for(int i = 0; i < nums.length; i++) {
        
        	//nums[i]의 값의 자리 수가 2의 자리 수로 짝수일 때 cntEvenNumberOfDigits에 1을 더해준다.
			if(nums[i] < 100 && nums[i] > 9) {
				cntEvenNumberOfDigits++;
				continue; 
                
            //nums[i]의 값의 자리 수가 4의 자리 수로 짝수일 때 cntEvenNumberOfDigits에 1을 더해준다.
			}else if(nums[i] < 10000 && nums[i] > 999) {
				cntEvenNumberOfDigits++;
				continue;
                
            //nums[i]의 값의 자리 수가 6의 자리 수로 짝수일 때 cntEvenNumberOfDigits에 1을 더해준다.    
			}else if(nums[i] < 1000000 && nums[i] > 99999) {
				cntEvenNumberOfDigits++;
				continue;
			}
		}
        //반복문을 통해 더해진 짝수 자리의 수를 가진 값의 개수를 반환
        return cntEvenNumberOfDigits;
    }
}
for문으로 nums[i]의 값을 반복해서 조회하면서 짝수자리의 값을 if문을 통해 필터링해 반환되는 값에 1을 더해준다.
제약조건에 nums[i]의 값이 7자리 수를 넘지 못하기 때문에 if문을 활용했다.

continue는 반복문을 제어하는 문법이다.
continue를 만나면 잔여 로직이 남아도 현재의 로직을 종료하고 다시 반복문으로 돌아간다.

위의 간단한 상황에서는 굳이 써주지 않아도 괜찮다고 생각이 들지만 if문이 다 끝난 후에 로직이 남아있다거나 
하나의 조건으로 중복되는 true값이 성사되면 원치 않는 값을 얻을 수 있기 때문에 사용하였다.

Runtime: 2 ms
Memory Usage: 43.5 MB

해당 풀이를 조금 더 가독성을 높이고 빠르게 처리하기 위해 foreach문을 활용하고
자리 수 마다 조건을 따로 걸었던 if문을 하나의 조건으로 취합해주었다.

class Solution {
    public int findNumbers(int[] nums) {
		int cntEvenNumberOfDigits = 0;
				
		for(int i : nums) {
			if((i < 100 && i > 9) || (i < 10000 && i > 999) || (i < 1000000 && i > 99999)) {
				cntEvenNumberOfDigits++;
				}
		    }
		    return cntEvenNumberOfDigits;
    }
}

메모리를 가장 적게 사용한 샘플(40.3MB)

class Solution {
    public int findNumbers(int[] nums) {
        int count = 0; 
        int temp = 0;  
        boolean isEven = false;
        for (int i = 0; i < nums.length; i++){
            temp = Math.floorDiv(nums[i],10);
            while(temp != 0){
                temp = Math.floorDiv(temp,10);
                if(isEven)
                    isEven = false;
                else
                    isEven = true;
            }
            if(isEven)
                count++;
            isEven = false;
        }
        return count;
    }
}
이 로직은 Math.floorDiv(a,b)함수와 Boolean를 이용한 방법이다.
temp에 nums[i]의 값을 담아 0이 될때 까지 10을 계속해서 나눈다.

만약 2자리수 이상의 값이라 while문이 동작하게 된다면 첫 동작에 isEven의 초기 값이 
false기 때문에 while문 안의 if 조건(true)을 충족시키지 못해 else로 흘러 true로 값이 저장된다.

이때 temp값이 0이라면 isEven이 true 즉 자리 수가 짝수인 값이기 때문에 count에 1이 더해지고 0이 아니라면 
while문을 반복하게 되어 if조건을 만족해 false를 얻게 된다.

결론적으로 while문은 2자리 수 이상의 값 부터 동작하게 되고 홀수면 false 짝수면 true를 얻어지는 로직이다.

메모리를 두번째로 적게 샘플(41.0MB)

class Solution {
    public int findNumbers(int[] nums) {
        int count=0;
        
        for(int i=0; i<nums.length;i++){
            int digits = 0;
            
            while(nums[i] > 0){
                nums[i] /= 10;
                digits++;
            }
            if(digits%2 == 0)
                count++;
            digits = 0;
        }
        return count;
    }
    
}
첫번째로 빠른 샘플과 로직은 비슷하다
다만 차이점은 boolean 아니면 나머지 연산자(%)를 활용 유무의 차이이다.

nums[i]의 값이 0보다 클 경우 while문이 동작하여 0이 될 때 까지 10을 나누어주고
10을 나눈 횟수 만큼 digits라는 변수에 값을 1씩 더해준다.

이후 나머지 연산자를 활용하여 nums[i]의 값에 10을 나눈 횟수를 2로 나누어 나머지가 0일때 즉, 10으로 나눈 횟수가 짝수번일때 결과 값을 반환해주는 count에 1을 더해준다.

0개의 댓글