나의 답)
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
는 절대값(absolute value)
을 구하는 함수인데,
절대값이란 숫자에서 그냥 부호를 제거한 값이라고 생각하면 된다.
양수는 그대로 양수로 유지가 되고, 음수는 예를 들어 -3 이라고 하면 절대값은 3인 것.
이 문제에서 abs
의 역할은
abs($0 - n)
는 배열의 각 원소인 $0
와 정수 n
의 차이를 계산하고 이걸 절대값으로 변환하는 역할인데,
이렇게 하면 두 값 간의 거리르 비교할 수 있게 된다.
이 절대값의 거리를 기준으로 가장 작은 값을 찾는 것이 핵심이기 때문이다.
근데 문제를 보면 제한사항에 숫자는 무조건 1 이상의 숫자인데,
왜 굳이 음수까지 확인해주는 절대값이 필요할까? 싶을 것이다.
나도 그랬다 ㅎㅎㅎ
사실 절대값을 하지 않았을 때 모르고 그냥 했었는데 시간 초과가 나왔고,
하나는 기대값이 다르다고 나와서 틀렸었다.
num - n
과 result - n
의 결과는 양수와 음수의 가능성을 모두 포함하기 때문에
차이를 비교할 때 거리를 나타내기 위해 절대값 처리가 필요하다고 한다.
아까 말한 제한사항이 양수라고 하더라도!!!
"가까운 거리"
를 비교하는 과정에서 크기와 부호에 관계없이 두 값 간의 차이를 확인하려는 경우에는 abs(절대값)
를 사용하는 것이 가장 안전하다.
왜냐하면 절대값은 차이를 항상 양수로 변환해 비교를 단순하게 만들어주기 때문이다.
if abs(num - n) < abs(result - n)
조건을 나눠서 하나하나 보자면 우선 위 첫번째 조건은
num
과 n
의 절대값이 result
와 n
의 차이보다 작다면 num
이 더 가까운 숫자일 것이다.
그러면 result
를 num
으로 갱신하고,
|| (abs(num - n) == abs(result - n) && num < result)
두번째 조건에서 두 숫자가 같은 거리인지를 먼저 확인한다.
혹시라도 num
과 result
가 기준값 n
으로부터 떨어진 거리가 같을 수도 있기 때문이다.
이때는 어느 값을 선택해야하는지 추가적인 기준이 한번 더 필요하기에
혹시라도 같은 거리라면 더 작은 숫자를 선택하라고 지정한 것이다. (문제에서 그랬다)
abs(num - n) < abs(result - n) || (abs(num - n) == abs(result - n) && num < result)
코드를 보면 OR 연산자
와 AND 연산자
를 사용했는데,
or연산자는 둘 중 하나라도 참이면 전체 조건이 참이 되는 거라서
첫번째 조건에서 num
이 result
보다 더 가까운지 확인하고,
두번째 조건에서 num
과 result
의 거리가 같을 때 num
이 더 작은지 확인하는 조건이다.
만약 첫번째 조건이 true
라면 굳이 두번째 조건은 검사할 필요가 없이 true
가 되는거고,
조건 1이 false
라면 조건 2를 확인할 것이다.
(abs(num - n) == abs(result - n) && num < result)
그리고 and연산자
는 양쪽 조건이 모두 참일 때 전체 조건을 참으로 만든다.
위랑 비슷한 설명이긴하지만 한번 더 설명해보겠다.
첫번째 조건에서 숫자가 같은 거리인지 확인했고,
두번째 조건에서 같은 거리라면 num이 더 적은지를 확인 한 것이다.
그래서 첫번째 조건이 false
라면 전체 조건이 다 false
로 판단해버릴 수 있다.
result = num }
return closest
그리고 값을 갱신해준다.
방금 위에서 논리 연산자로 찾은 값이 참이라면 result
를 num
으로 갱신해주는 것이다.
그러면 더 가까운 값이나 같은 거리였다면 더 작은 값으로 업데이트가 될 것이다.
그렇게 n에서 가장 가까운 값을 result
로 반환만 해주면 된다.
문제를 이해하는 과정이 이틀이나 걸렸다.
사실 첫날에는 잘 모르니, 가까운 수를 찾는다는 조건과 같은 거리일 때
더 작은 값을 선택하는 조건을 어떻게 코드로 짜야할 지 고민을 길게 한 듯 하다.
그러다가 미뤄둔 swift 의 문법책을 보면서 논리연산자 부분을 읽으며 이걸로 판별을 하는게 좋겠다 라고 생각했고,
abs 절대값을 이용하는 아이디어는 사실 검색해서 알아봤다 ㅠ
아무리 해도 저 절대값 없이는 계속 오류가 났어서
비슷한걸로 magnitude
도 있었는데 이건 UInt
로 자료형으로 반환한다고 하길래
UInt는 또 뭐야 했는데 0이상의 값만 저장이 가능한 Int였다.
음수값을 가질 수 없어서 저걸 사용해도 무방하긴 했음..
무튼 이렇게 풀면서 이런 자료형 공부도 자동으로 자동으로 되니 좋았다.
아~ 어려워~~!~!
하나의 for문 안에서 AND랑 OR로 한 번에 해결하는 거 너무 똑똑하다..