티스토리 뷰

코드카타

 

뒤에 있는 큰 수 찾기

 

문제

 

 

풀이

class Solution {
    fun solution(numbers: IntArray): IntArray {
    	// 결과를 저장할 배열로, 모든 요소의 초기값을 -1로 설정
        val res = IntArray(numbers.size) { -1 } 
        
        // 인덱스를 저장할 스택 초기화
        val stack = mutableListOf<Int>() 
		
        // 주어진 정수 배열의 각 요소를 순회
        for (i in numbers.indices) {
            // 스택이 비어있지 않고, 스택의 마지막 인덱스가 가리키는 숫자가
            // 현재 숫자보다 작을 경우, 해당 인덱스의 값을 현재 숫자로 갱신
            while (stack.isNotEmpty() && numbers[stack.last()] < numbers[i]) {
                // 스택의 마지막 요소를 제거 후, 결과 배열에 현재 숫자를 할당
                res[stack.removeAt(stack.size - 1)] = numbers[i]
            }
            stack.add(i) // 현재 인덱스를 스택에 추가
        }
        
        return res 
    }
}

결과 배열의 초기값을 -1로 설정함으로써 

어떤 원소보다 큰 숫자를 찾지 못했을 때의 경우를 처리한다.

 

stack.last()는 스택이 비어있을 때 호출하면 런타임 에러를 발생시키므로

stack.isNotEmpty()로 스택에 값이 있는지 확인해줘야한다.

 

 

회고

스택에 인덱스를 저장시키는 방식도 

잘 기억해놨다가 유용하게 써야겠다.

 


 

챌린지반 2주차 세션 정리

 

SOLID 디자인 원칙

 

SOLID 디자인 원칙이란 객체지향 프로그래밍에서 준수해야 할 5가지 설계 원칙이다.

 

 

단일 책임 원칙 

 

각 클래스는 하나의 책임만을 가지도록 설계되어야 한다.

 

단일 책임 원칙을 준수하여 클래스를 설계하게 된다면

각 클래스의 역할과 동작을 이해하기 쉬워지며,

수정이 간단해지고, 재사용성이 향상된다.

 

 

위 예제코드는 커피를 만드는 기계 클래스를 정의하는 구문이다.

커피를 만들때는 원두를 갈고, 물을 데우고, 커피를 추출하는 등의 과정이 필요하다.

 

이러한 동작들을 하나의 클래스에 정의하는 대신,

각 과정을 담당하는 클래스에 따로 정의하고,

상위 클래스에서 해당 클래스들의 인스턴스를 사용한다.

 

위 예제 코드는 상위 클래스와 하위 클래스의 관계에서 동작을 분리하여

각각의 클래스가 하나의 역할만 수행하도록 하는 단일 책임 원칙을 준수한다.

 

단일책임원칙을 준수하여 하위 클래스들을 설계하면 

해당 클래스들을 재사용하기 확실히 편해진다.

 

그런거 신경안쓰고 설계해도 되는데 그러면 퇴근시간이 늦어진다고 한다

 

 

개방-폐쇄 원칙

 

하위 클래스와 상위 클래스를 분리하여 

하위 클래스를 주입만 하면 바로 상위 클래스에서

동작할 수 있게끔 하는게 개방 폐쇠 원칙이다.

 

 

상위 클래스를 이런식으로 구현하면 새로운 커피 종류를

추가할 때마다 상위 클래스를 수정해야 되는 문제가 있다. 

 

 

Coffee라는 인터페이스 내에 추상메소드를 정의하고

각 커피종류에 해당하는 클래스에서 해당 인터페이스를 구현하여

각 클래스 내에서 커피를 추출하는 메소드를 정의한한다.

 

이런식으로 구현하면 상위 클래스를 수정할 필요가 없어진다.

 

해당 예제에서는 별로 와닿지 않을 수 지만 프로그램이 커질 수록

상위클래스를 수정하 되면 버그가 생길 확률이 높아진다고 한다.

 

따라서 인터페이스를 사용하여 동작을 정의하고,

이를 구현하는 클래스를 분리할 필요가 있다.

 

 

리스코프 치환 원칙

 

상위 타입의 객체를 대체할 수 있도록 하위 타입의 객체를

설계하는 것을 리스코프 치환 원칙이라고 한다.

 

 

brewCoffeeWithMachine는 부모 클래스를 생성자로 받지만

자식 클래스가 생성자로 전달되는 경우에도 문제없이 실행된다.

 

리스코프 치환 원칙을 준수하면 예외를 발생시킬 일이 없게 된다.

 

 

인터페이스 분리 원칙

인터페이스를 상속하는 클래스는 인터페이스의 모든 메서드를 구현해야한다.

 

따라서, 하나의 인터페이스를 모든 추상 메서드가 정의되어 있다면,

구현할 클래스에서 필요없는 기능은 예외처리를 해줘야한다.

 

 

이를 방지하기 위해서 지켜야 하는게 인터페이스 분리 원칙이다.

 

위 코드에서는 각 기능별로 인터페이스를 분리한 뒤,

각 클래스가 필요한 기능만 구현할 수 있도록 각 인터페이스를 다중 상속하였다.

 

 

의존성 역전 원칙

 

의존성 역전 원칙이란 고수준 모듈은 저수준 모듈에 의존해서는 안 되며,

모든 모듈은 추상화에 의존해야 한다는 원칙이다.

 

여기서 고수준 모듈이란 interface와 추상 클래스에 해당하며,

저수준 모듈이란 고수준 모듈을 구현하는 클래스 및 객체에 해당한다.

 

저수준 클래스는 자주 변경되고, 새로운 것이 추가될 때마다

고수준 클래스가 영향을 받기 쉬우므로 의존관계를 역전시켜야 한다.

 

 

해당 코드에서 상위 클래스는 하위 클래스의 구현에 의존하지 않기에

생성자에 무슨 클래스가 들어오던 정해진 함수만을 호출해주면 된다. 

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
글 보관함