[TIL] 0307 알고리즘 풀이

한철희·2024년 3월 7일
0

TIL

목록 보기
4/57

오늘도 알고리즘 풀이로 TIL을 작성한다.
빠르게 가보자

반복문에 중독되버린 것인지 이것도 반복문으로 풀었다

func solution(_ n:Int) -> String {
    var result = ""
    for i in 1...n {
        if i % 2 == 0 {
            result += "박"
        } else {
            result += "수"
        }
    }
    return result
}

단순하게 i가 홀수일 때 "수"를 짝수일 때 "박"을 추가하도록 했다.
문자열끼리는 +연산이 가능해서 쉽게 추가했다

무난하게 통과했지만 요즘 너무 반복문만 사용하는것 같아서
메소드를 이용해서 다시 풀이해봤다

func solution(_ n: Int) -> String {
    return (1...n).map { $0 % 2 == 0 ? "박" : "수" }.joined()
}

음 확실히 간결해졌다. 이대로 제출하니 통과했다
후에 익숙해지긴 하겠지만 아직 어색한 방법인것같다
아 저번에 실행 시간 차이가 나던게 신기해서 이번에도 결과를 봤는데
이게 첫번째 풀이 방법의 소요시간이고
다음이 두번째 풀이 방법이다
저번처럼 소요시간 자체는 메소드를 사용하는 쪽이 더 많이 소모된다.

코드가 깔끔하게 작성되는 것도 좋지만 실제 데이터 인풋이 많은 상황에서는 단순 반복문이 성능상으론 좋을 수도 있겠다고 생각했다.
실제 프로젝트에 들어갔을때 어떤걸 써야할지 고민이 많이 될거같다.



다음 문제인데 또 반복문이다
이제 반복문없이 살 수 없을지도

func solution(_ a:[Int], _ b:[Int]) -> Int {
    var result = 0
    for i in 0..<a.count {
        result += a[i] * b[i]
    }
    return result
}

이것 역시 다른 방법을 찾아 보려고 다른 분들의 풀이를 참고해봤다

func solution(_ a:[Int], _ b:[Int]) -> Int {
    return zip(a, b).map(*).reduce(0, +)
}

처음본 건 zip이라는 메소드인데 배열을 결합시켜주는 연산자인것 같다.
예를 들어 a = [1, 2, 3], b = [4, 5, 6]이라는 배열이 있다면 이것을 (1,4), (2,5), 3,6)같은 방식으로 결합해준다.
그후 map(*)을 통해 곱연산자를 추가하고 ex)(1 * 4)
reduce메서드로 모든 요소를 결합하여 반환한다.



음.. 이 문제는 처음에 보고 좀 고민을 했다
처음에 left부터 right까지의 수를 반복문으로 돌리고
약수를 찾은후 조건문을 통해 풀려고 했으나
약수도 반복문을 통해서 해야하기 때문에 이중 for문이 될거같아서 고민했다

고민해봐도 이 방법밖에 생각이 안나서 일단 풀었다

func solution(_ left:Int, _ right:Int) -> Int {
    var result = 0
    
    for i in left...right {
        let count = factor(i)
        result += (count % 2 == 0) ? i : -i
    }
    return result
}

func factor(_ num: Int) -> Int{
    var count = 0
    
    for i in 1...num {
        if num % i == 0 {
            count += 1
        }
    }
    return count
}

약수 구하는 부분을 factor함수로 빼서 그나마 가독성을 높이려고 했다
무튼 해결은 했지만 뭔가 찜찜해서 다른 사람들 풀이를 봤다
눈에 띄는 풀이는 아래의 것이다

func solution(_ left: Int, _ right: Int) -> Int {
    return (left...right).map { i in (1...i).filter { i % $0 == 0 }.count % 2 == 0 ? i : -i }.reduce(0, +)
}

고차함수를 사용해서 한줄로 길게 작성하셨다.
메서드에 대한 이해도는 높아 보이지만 개인적으로는 가독성이 좀 떨어진다고 생각했다

그 외 다른 사람들의 풀이는 내것과 유사하나 조금씩 변경점이 있는 정도다.



이 문제는 처음에 보고 어 쉬운데?하고 접근했다
처음에는 아래처럼 풀었다

func solution(_ s:String) -> String {
    return Array(s).sorted(by:>).joined(separator: " ")
}

근데 오류가 나서 아래와 같이 수정했다.

func solution(_ s: String) -> String {
    return String(s.sorted(by: >))
}

근데 이 풀이는 통과했다가도 런타임 에러가 뜨거나 특정 테스트에서 계속 시간이 초과되는 경우가 있어서 다시 수정했다

func solution(_ s: String) -> String {
    let sortedCharacters = s.sorted(by: >)
    return String(sortedCharacters)
}

이렇게 하니 특이사항 없이 통과했다
전의 풀이와 비교하면 문자열의 정렬을 변수에 할당을 했느냐 안했느냐의 차이인데 왜 에러가 떴는지는 모르겠다

다른 사람의 풀이중에서 참고할만한 것은

func solution(_ s:String) -> String {
    return String(s.sorted { $0 > $1 })
}

이 풀이였다
단순 내림비교가 아닌 두개의 요소를 비교하여 정렬하는 방식
어찌보면 이 방식이 더 효율적일수 있겠다
쉬운문제 같았는데 제법 애먹은 문제였다



갑자기 방대해진 설명에 쉽지 않아보이는 문제라고 생각했다.
그래도 차분히 뜯어보니 풀이 방법이 보였다

  • money에서 놀이기구 이용료의 총합 빼기
  • 금액이 부족하면 음수가 나올것
  • 절대값을 씌워서 반환 or 0을 반환

이렇게 포인트를 잡고 풀었다

func solution(_ price:Int, _ money:Int, _ count:Int) -> Int64{
    var answer:Int = -1
    var sum: Int = 0
    for i in 1...count {
        sum += price * i
    }
    answer = money - sum
    return answer < 0 ? Int64(abs(answer)) : 0
}

마지막 return부분에서 괜히 헷갈렸는데
돈이 모자랄때만 0보다 값이 작고 나머지 상황(돈이 딱 맞거나, 충분하거나) 하는 상황은 0이상의 값이 나온다
이 부분은 급하게 푸느라 헷갈린것같다

다른 사람들 풀이를 보니 정말 간단하게 푼 사람들이 있더라

func solution(_ price:Int, _ money:Int, _ count:Int) -> Int{
    return max((count + 1) * count / 2 * price - money , 0)
}

이렇게 간단하게 푸는 사람들 보면 존경스러울 정도
또 하나의 풀이가 있었는데

func solution(_ price:Int, _ money:Int, _ count:Int) -> Int64{
    let totalPrice = price * (count * (count+1)/2)

    if money >= totalPrice {
        return 0
    }

    return Int64(totalPrice - money)
}

둘의 겉모양은 다르지만 (count * (count+1)/2)이 부분이 공통인데 찾아보니 등차수열을 이용한 방식이더라
이렇게 수학적인 사고가 들어간 풀이는 처음보는거 같아서 신기했다. 한 수 배워가는 느낌


문자열 공부하자고 어제 생각했는데 바로 관련 문제가 나왔다
비교적 간단하게 풀이했다

func solution(_ s:String) -> Bool {
    if s.count == 4 || s.count == 6 {
        return Int(s) != nil ? true : false
    } else {
        return false
    }
}

난 이것도 제법 간단하게? 풀었다고 생각했는데
뛰는 놈위에 나는 놈 있다더니 더 심플한 풀이가 있다

func solution(_ s:String) -> Bool {
    return (Int(s) != nil && (s.count == 4 || s.count == 6)) ? true : false
}

내가 한 풀이를 축약한 느낌의 코드다.
이 풀이가 가장 와닿았는데
요즘 시도해보려는 메서드를 사용하는 간략한 풀이 방법인데 조건을 설정하는 부분에서 생각이 꼬여서 안했던 방법이다.
다음 문제 풀이부터는 좀 더 차분하게 생각을 정리할 수 있도록 해야겠다

profile
초보 개발자 살아남기

2개의 댓글

comment-user-thumbnail
2024년 3월 8일

알고리즘 마스터.. 모르는 문제 여쭤보겠습니다 :)

1개의 답글