티스토리 뷰
백준 2331, 반복수열 문제 설명
자세한 문제 설명은 직접 확인하고 푸시길 바랍니다.
반복수열 문제는 최근 수열 값의 각 자리수를 P번 제곱한 합을 다음 수열로 쌓아나갈때, 반복되는 수열이 발생하는데, 이때 반복되는 수열 이전의 반복되지 않았던 수열 길이를 구하는 문제입니다.
실버4문제입니다. 오랜만에 문제 하나 먹었습니다.
생성되는 수열의 연산 규칙은 위 내용을 참고 바랍니다. A라는 숫자로부터 시작해서 각자리의 숫자를 P번 제곱한 합을 다음 수열 값으로 이어가면서 반복수열을 확인하고, 반복되는 수열 이전의 수열길이를 출력하면 되는 문제입니다.
수열의 반복은 swift의 해시 자료구조인 dictinoary를 사용하겠습니다. 또한 제곱의 경우 거듭제곱 알고리즘을 이용해서 O(logN)의 시간복잡도로 연산하도록 하겠습니다.
*사실 본 문제에서는 제곱을 해봐야 5번 뿐이기에 거듭제곱 알고리즘을 사용하지 않아도 되긴 합니다만.. 상기 차원으로 사용할게요!
바로 swift언어로 본 문제를 풀어보겠습니다!
백준 2331, 반복수열 문제 swift 풀이
dictinoary, 거듭제곱 알고리즘 활용
먼저, A, P를 입력받았습니다. dic은 각 인덱스 값에 대한 P번 제곱했을때의 결과값이 들어갑니다. 이때 [0, 1]을 넣는 이유는 자릿값이 0, 1인 경우에는 몇번의 제곱을 해도 그대로 0, 1이기때문에 미리 넣어둘 수 있었습니다. dic2는 앞서 말했던, 수열의 반복여부를 판단하는데 사용하며, 반복되지 않은 수에 대한 인덱스값을 넣어서 반복값이 들어왔을 경우, 반복되는 시작점을 바로 알아내는데에 사용합니다.
Int 익스텐션 함수를 만들어봤습니다. 그냥 기본 클로져, 함수 등으로 구현해서 사용해도 무방합니다. 거듭제곱 알고리즘을 활용해서 O(logN)의 시간복잡도 특정 제곱 결과값을 반환해주는 메서드를 구현했습니다.
24 ~ 26행) 자릿값이 2 ~ 9 일 때에 대한 P제곱 결과값을 순차적으로 dic에 넣어줍니다.
28 ~ 31행) value에 수열 첫번째 값인 A를 넣었습니다. cnt는 현재 수열이 몇번째 수열인지 확인하는데 사용합니다. (zero-based index) lastIdx는 그냥 없는 셈 쳐주세요. 사용하지 않네요 ㅎㅎ..
32 ~ 47행) 최근 연산한 수열 값 value에 대한 각 자리의 P제곱 합을 연산하고, 중복여부를 체크하는 로직입니다. 여기에서 중복이 발견 될 경우, 중복 수열의 시작점 이전까지 있었던 수열이 중복되지 않는 수열이죠.
문제 설명에 나온 예제 입력을 예로 들자면, ex) 57, 74, 65, 61, 37(중복 수열값의 시작점) ..... 37(동일 값 발견 시점) => 중복 수열 시작점 이전까지의 수열이 중복되지 않은 수열입니다.
40행) 이때 중복수열값의 시작점 인덱스는 zero-based index이므로, 이를 그대로 반환하면 반복되지 않는 수열의 갯수를 구할 수 있습니다.
오늘은 실버4 티어의 반복수열 문제를 dictionary, 거듭제곱 알고리즘 등을 활용해서 풀어봤습니다. 질문, 의견 댓글 환영합니다. 즐거운 코딩 되시길 바랍니다.
전체코드 아래 공유하겠습니다!
let ip = readLine()!.split(separator: " ").map { Int(String($0))! }
let (A, P) = (ip[0], ip[1])
var dic = [0, 1]
var dic2 = [Int: Int]()
extension Int {
func customPow(cnt: Int) -> Int {
var result = 1
var cnt = cnt
var flag = self
while cnt > 0 {
if cnt % 2 == 0 {
flag *= flag
cnt /= 2
} else {
result *= flag
cnt -= 1
}
}
return result
}
}
(2...9).forEach { num in
dic.append(num.customPow(cnt: P))
}
var value = A
var cnt = 1
var lastIdx = 0
dic2[value] = 0
while true {
var result = 0
while value > 0 {
result += dic[value % 10]
value /= 10
}
if dic2[result] != nil {
print(dic2[result]!)
break
}
dic2[result] = cnt
value = result
cnt += 1
}
'알고리즘 정보 > Swift 알고리즘' 카테고리의 다른 글
프로그래머스 2단계 연습문제, 롤케이크 자르기 swift 풀이 (0) | 2023.02.01 |
---|---|
백준 13565 침투, DFS 깊이우선탐색 swift언어 문제풀이 (0) | 2022.02.07 |
백준 1799, 비숍 백트래킹 backtracking 스위프트 문제풀이 (0) | 2021.12.21 |
종만북 비트마스크 연산자 기본예제, swift언어로 보기 (0) | 2021.11.21 |
백준 16956 늑대와 양, 실버문제 애드혹 알고리즘 swift 풀이 (0) | 2021.10.10 |
- Total
- Today
- Yesterday
- swift string
- 김프매매
- publisher
- swift언어
- 프로그래머스
- swift reduce
- createML
- 알고리즘
- 컬렉션
- CoreML
- 프로그래머스swift
- swift 기초
- 백준swift
- swift
- 알고리즘문제
- 백준알고리즘
- swift문제
- swift알고리즘
- ios
- Collection
- Protocol
- 자연어처리
- swift 문자열
- 스위프트
- SwiftUI
- 개발자문서
- 프로토콜
- 부스트코스
- Swift 알고리즘
- uikit
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |