문제 설명
- 2m,3m,4m 거리에 시소가 설치해져있다
- weights배열에서 2명씩 뽑아서 균형이 잘 이루어지게끔 해라
- m랑 몸무게의 비율이 일치하면된다.
아래 사진과 같은 느낌이라 보시면 될 것 같다 !
문제 접근
- 일단 두개씩 짝 지어줘야하는 상황이고, 나올 수 있는 비율이 1:1을 제외하고는 2:3, 3:4, 2:4 이거 3개라고 생각했다. 3:2, 4:3 처럼 뒤집어진 상황도 있겠지만 이거는 배열을 처음에 정렬하고 들어가면 해결되는 문제라고 생각했다.
- 1:1도 제외한 이유는 같은 원소는 그냥 SET으로 만들면서 처음에 그 값을 최종 방법론에 더해줬다. 그러면 1:1해서 없어진거랑 같은효과이기 때문 !
제출 코드
import Foundation
func solution(_ weights: [Int]) -> Int64 {
let TMP: [Float] = [2, 3, 4]
let SET: Set<Float> = [TMP[0] / TMP[1], TMP[1] / TMP[2], TMP[0] / TMP[2]]
var answer = 0
var arr_weights = Array(Set(weights)).sorted()
answer += weights.count - arr_weights.count // 중복 날려주기 , 이러면 1:1 안봐도됨
// 1:2, 2:3 , 3:4 ,
while arr_weights.count > 1 {
let current_target = arr_weights.removeLast() // 마지막애를 뽑아줬음(큰친구)
for item in arr_weights {
let tmp: Float = (Float(item) / Float(current_target))
if SET.contains(tmp) {
answer += 1
}
}
}
return Int64(answer)
}
Float
로 큰값에서 작은값을 나눈 애를 미리 정해놓은 SET배열에서 찾아주는 형태로 수행을 했고, 예제가 잘나와서 한 번에 잘 통과되나했는데..
꽥☠️
채점 결과
정확성: 17.6
합계: 17.6 / 100.0
3개맞고 나머지를 다 틀렸다. 오류는 아니고 틀린거로 찍혀서 어딘가 로직에 결함이 있는 것 같았다.
코드 수정
중복부분을 없애고 SET배열에서 1:1비율을 추가를 해주도록 하겠다.
채점 결과
정확성: 35.3
합계: 35.3 / 100.0
조금 오르긴했는데, 이제 나머지 친구들이 시간초과가 나오는 것으로 바뀌었다...
100 ≤ weights[i] ≤ 1,000
라는 점을 잘 고려하라는 이야기를 듣고 이걸 딕셔너리형태로 바꿔주기로 했다.
var dict: [Float: Int] = [:]
for item in weights {
dict[Float(item), default: 0] += 1
}
그리고 1:1일때는 nC2니까 이를 dict를 한 번 순회해주면서 수행했다.
for item in dict {
answer += (item.1 * (item.1 - 1) / 2)
}
이렇게 해주면 5개 같은게 있을 때 5*4에 순서 고려하지 않으니 /2 해서 10이 나올 것이다.
그리고 코드는 원래 있던 구조 SET을 다시 살려서 차용하되, 비율이 있을 때 dict를 참조해서 각각의 중복되는 값을 곱해주면서 경우의 수를 챙겼다.
import Foundation
func solution(_ weights: [Int]) -> Int64 {
let TMP: [Float] = [2, 3, 4]
let SET: Set<Float> = [TMP[0] / TMP[0], TMP[0] / TMP[1], TMP[1] / TMP[2], TMP[0] / TMP[2]]
var answer = 0
var dict: [Float: Int] = [:]
for item in weights {
dict[Float(item), default: 0] += 1
}
for item in dict {
answer += (item.1 * (item.1 - 1) / 2)
}
var arr_weights = Array(Set(weights)).sorted().map { Float($0) }
while arr_weights.count > 1 {
let current_target = arr_weights.removeLast() // 마지막애를 뽑아줬음(큰친구)
for item in arr_weights {
let tmp: Float = (item / current_target)
if SET.contains(tmp) {
answer += 1 * dict[item]! * dict[current_target]!
}
}
}
return Int64(answer)
}
아직 문제를 풀 때 시간이 오래 걸리기는 하는데, 그래도 점점 나아지고 있는게 느껴져서 뿌듯했다.
채점 결과
정확성: 100.0
합계: 100.0 / 100.0
타인의 코드
import Foundation
func solution(_ weights:[Int]) -> Int64 {
var result = 0
var counter: [Double: Int] = [:]
for w in weights {
counter[Double(w), default: 0] += 1
}
let candis: [Double] = [2/3, 2/4, 3/2, 3/4, 4/2, 4/3]
for (key, value) in counter {
result += value * (value - 1)
for c in candis {
if let oppo = counter[key * c] {
result += value * oppo
}
}
}
return Int64(result) / 2
}
- candis를 찾아줄 생각만했는데, 반대로 candis에 있는 애를 곱해서 dict의 값과 비교하는데에서 좀 더 깊게 생각하지 못했음을 반성했다. 괜히 값끼리 곱해주고 하느라 억지로 float해주고 형태 맞춰주느라 고생했는데, 결과값을 중간으로 끌어와서 값을 도출하는게 너무 좋다고 느꼈다.
- 그리고 나는 sorted()를 해줘서 2/3을 챙기고 3/2는 안챙기는 방식으로했는데, 순서상관없이 다해주고 맨마지막에 /2 해줘서 까끔한 코드가 된 것 같다.