[Swift/프로그래머스] 가까운 수 (feat. abs)

sonny·3일 전
4

TIL

목록 보기
46/48


나의 답)

func solution(_ array: [Int], _ n: Int) -> Int {
    var result = array[0]
    for num in array {
        if abs(num - n) < abs(result - n) || (abs(num - n) == abs(result - n) && num < result) {
            result = num
        }
    }
    return result
}

풀이 과정

알고리즘 반이 생겨서 세 문제를 받게 되었는데, 이게 제일 뭔가 어려웠다.

심지어 다른건 난이도가 1단계이고 이건 0단계인데... 어렵던데 ㅜ 라며 부정했다.

우선 array에 들어있는 정수를 정리해야했다.

var result = array[0]

result 라는 변수를 먼저 선언해주고 배열의 첫번째를 0으로 초기화 해준다.

그래의 기준점을 만들 수가 있어서 배열을 순회하게되면 가장 가까운 값을 찾아나갈 수가 있기 때문이다.

그리고 그 뒤에는 이제 반복문으로 array의 모든 숫자들을 하나씩 순회해 준다.

for num in array {
      if abs(num - n) < abs(result - n) || (abs(num - n) == abs(result - n) && num < result) {

num과 n의 거리 ( abs(num - n) ) 를 계산해서 result랑 비교를 해주어야한다.


abs가 무엇인가

abs절대값(absolute value)을 구하는 함수인데,

절대값이란 숫자에서 그냥 부호를 제거한 값이라고 생각하면 된다.

양수는 그대로 양수로 유지가 되고, 음수는 예를 들어 -3 이라고 하면 절대값은 3인 것.

이 문제에서 abs의 역할은

abs($0 - n) 는 배열의 각 원소인 $0와 정수 n의 차이를 계산하고 이걸 절대값으로 변환하는 역할인데,

이렇게 하면 두 값 간의 거리르 비교할 수 있게 된다.

이 절대값의 거리를 기준으로 가장 작은 값을 찾는 것이 핵심이기 때문이다.

근데 문제를 보면 제한사항에 숫자는 무조건 1 이상의 숫자인데,

왜 굳이 음수까지 확인해주는 절대값이 필요할까? 싶을 것이다.

나도 그랬다 ㅎㅎㅎ

절대값을 적용하지 않았을 때 오류 남

사실 절대값을 하지 않았을 때 모르고 그냥 했었는데 시간 초과가 나왔고,

하나는 기대값이 다르다고 나와서 틀렸었다.

num - nresult - n의 결과는 양수와 음수의 가능성을 모두 포함하기 때문에

차이를 비교할 때 거리를 나타내기 위해 절대값 처리가 필요하다고 한다.

아까 말한 제한사항이 양수라고 하더라도!!!

"가까운 거리"를 비교하는 과정에서 크기와 부호에 관계없이 두 값 간의 차이를 확인하려는 경우에는 abs(절대값)를 사용하는 것이 가장 안전하다.

왜냐하면 절대값은 차이를 항상 양수로 변환해 비교를 단순하게 만들어주기 때문이다.


다시 문제로 돌아와서

if abs(num - n) < abs(result - n) 

조건을 나눠서 하나하나 보자면 우선 위 첫번째 조건은

numn의 절대값이 resultn의 차이보다 작다면 num이 더 가까운 숫자일 것이다.

그러면 resultnum으로 갱신하고,

|| (abs(num - n) == abs(result - n) && num < result)

두번째 조건에서 두 숫자가 같은 거리인지를 먼저 확인한다.

혹시라도 numresult가 기준값 n 으로부터 떨어진 거리가 같을 수도 있기 때문이다.

이때는 어느 값을 선택해야하는지 추가적인 기준이 한번 더 필요하기에

혹시라도 같은 거리라면 더 작은 숫자를 선택하라고 지정한 것이다. (문제에서 그랬다)

여기서 논리연산자가 어떻게 이용되었나

OR 연산자)

abs(num - n) < abs(result - n) || (abs(num - n) == abs(result - n) && num < result)

코드를 보면 OR 연산자AND 연산자를 사용했는데,

or연산자는 둘 중 하나라도 참이면 전체 조건이 참이 되는 거라서

첫번째 조건에서 numresult보다 더 가까운지 확인하고,

두번째 조건에서 numresult의 거리가 같을 때 num이 더 작은지 확인하는 조건이다.

만약 첫번째 조건이 true라면 굳이 두번째 조건은 검사할 필요가 없이 true가 되는거고,

조건 1이 false 라면 조건 2를 확인할 것이다.

AND 연산자)

(abs(num - n) == abs(result - n) && num < result)

그리고 and연산자는 양쪽 조건이 모두 참일 때 전체 조건을 참으로 만든다.

위랑 비슷한 설명이긴하지만 한번 더 설명해보겠다.

첫번째 조건에서 숫자가 같은 거리인지 확인했고,

두번째 조건에서 같은 거리라면 num이 더 적은지를 확인 한 것이다.

그래서 첫번째 조건이 false라면 전체 조건이 다 false로 판단해버릴 수 있다.

result = num }

    return closest

그리고 값을 갱신해준다.

방금 위에서 논리 연산자로 찾은 값이 참이라면 resultnum으로 갱신해주는 것이다.

그러면 더 가까운 값이나 같은 거리였다면 더 작은 값으로 업데이트가 될 것이다.

그렇게 n에서 가장 가까운 값을 result로 반환만 해주면 된다.


음 ...

문제를 이해하는 과정이 이틀이나 걸렸다.

사실 첫날에는 잘 모르니, 가까운 수를 찾는다는 조건과 같은 거리일 때

더 작은 값을 선택하는 조건을 어떻게 코드로 짜야할 지 고민을 길게 한 듯 하다.

그러다가 미뤄둔 swift 의 문법책을 보면서 논리연산자 부분을 읽으며 이걸로 판별을 하는게 좋겠다 라고 생각했고,

abs 절대값을 이용하는 아이디어는 사실 검색해서 알아봤다 ㅠ

아무리 해도 저 절대값 없이는 계속 오류가 났어서

비슷한걸로 magnitude 도 있었는데 이건 UInt로 자료형으로 반환한다고 하길래

UInt는 또 뭐야 했는데 0이상의 값만 저장이 가능한 Int였다.

음수값을 가질 수 없어서 저걸 사용해도 무방하긴 했음..

무튼 이렇게 풀면서 이런 자료형 공부도 자동으로 자동으로 되니 좋았다.

아~ 어려워~~!~!

profile
iOS 좋아. swift 좋아.

2개의 댓글

comment-user-thumbnail
약 9시간 전

하나의 for문 안에서 AND랑 OR로 한 번에 해결하는 거 너무 똑똑하다..

1개의 답글