Neoself의 기술 블로그

알고리즘 지식 정리(10월 12일)[프로그래머스 레벨 1] 본문

개발지식 정리/알고리즘

알고리즘 지식 정리(10월 12일)[프로그래머스 레벨 1]

Neoself 2024. 10. 12. 22:21

제일 작은 수 제거하기

func removeLeast(_ arr:[Int]) -> [Int] {
    var arrMin = arr.min()
    return arr.count == 1 ? [-1] : arr.filter{$0 != arrMin}

}

filter함수로 매 요소마다 arr.min()함수를 호출하면 1번 케이스에서 시간초과를  겪는데, arr.min() 함수는 그 자체로 모든 요소를 1회 순회하며 O(n) 시간 복잡도를 갖기 때문이다. 따라서 arrMin 변수 선언 시에만 해당 함수를 실행하고, 이후 filter로 arr 순회할때 해당 변수를 재사용 할 경우 시간초과 문제를 해결할 수 있다.

 

핸드폰 번호 가리기

func phoneNum(_ phone_number:String) -> String {
    return phone_number.enumerated().map{(index,num) in (phone_number.count-4...phone_number.count-1).contains(index) ? String(num) : "*" }.joined()
}

함수 자체가 좀 더럽긴 한데, enumerated()함수로 주어진 String값에 대해 자릿수 index를 접근한 후, map 함수로 모든 Character를 순회하며 각 요소의 위치에 따라 반환값을 달리하였다. 이때 범위 연산자로 튜플을 생성하여 자릿수 위치 조건을 만들었다.

 

return String("\(String(repeating: "*", count: phone_number.count - 4))\(phone_number.suffix(4))")

다른 답변을 보니, String(repeating:,count:) 함수로 반복되는 String값을 생성한 후에, suffix를 통해 String의 마지막 4자리 String을 접근하여 반환값을 설정하였다.

 

내적

func naejuk(_ a:[Int], _ b:[Int]) -> Int {
    return a.enumerated().map {(id,num) in num*b[id]}.reduce(0,+)
    //return zip(a, b).map(*).reduce(0, +)
}

마찬가지로 enumerated함수로 id값을 접근 + reduce로 총합을 구하였는데, zip함수로 두개 시퀀스를 결합하여 연산을 처리한 것이 인상적이였다.

zip 함수는 아래와 같이 for문과 filter과 같은 고차함수에도 사용될 수 있다.

 

let names = ["name1","name2","name3"]
let scores = [24,42,64]
for (name,score) in zip(names,scores) {
    print(\(name) scored : \(score)
}


let sequence1 = [1, 2, 3, 4]
let sequence2 = [1, 2, 3, 5]
let differences = zip(sequence1, sequence2).filter { $0 != $1 }
print(differences) // [(4, 5)]

 

가운데 글자 가져오기

func midNum(_ s:String) -> String {
    let myArr = Array(s)
    return myArr.count%2==0 ? String(myArr[myArr.count/2-1...myArr.count/2]) : String(myArr[myArr.count/2])
}

String 타입의 경우 [2...3]을 붙여서 특정 범위의 String에 접근하는 것이 불가능하다. 이는 String.index와 같은 방법을 통해 진행되어야 하는데 시간 복잡도 측면에서 불리하기 때문에, Array로 변경한 후에 특정 범위에 대한 접근을 하도록 하자.