💬 문제
[코딩테스트 연습 - 이모티콘 할인행사](https://school.programmers.co.kr/learn/courses/30/lessons/150368)
💬 Idea
- 먼저 이모티콘 수에 맞는 할인율 조합을 구하자
- 어떻게 구할 것인가? → dfs 재귀함수를 만들어서 10, 20, 30, 40 각각을 돌며 array에 더한다.
- dfs 비교군을 줄이기 위해 user가 갖고 있는 가격 기준의 최저값을 구해 sales를 먼저 필터링해준다.
- ex. user = [[40, 10000], [25, 10000]] 의 경우 유저들이 구입할 최저 세일 비율이 30% 이므로 30, 40 만을 갖고 가격 조합을 만들어줄 수 있다. → 시간 절약 !
- 할인율 조합을 구한 뒤 해당 조합에서 이모티콘플러스 가입자 수와 판매액이 최댓값인지를 비교하자
💬 풀이
첫번째 시도 - 시간초과 [정확성 (75/100)]
varpercentArr:Set<[Int]>=[]func solution(users:[[Int]], emoticons:[Int])->[Int]{dfs(index:0, arr:[], max: emoticons.count)varemtiplusCnt=0varsumSale=0forpercentin percentArr {varcnt=0varsum=0foruserin users {varuserSum=0for(index, p)in percent.enumerated(){
// 유저의 기준비율에 맞는 이모티콘만 선별하기
if p >=user[0]{
userSum +=calDiscountPrice(Double(emoticons[index]),Double(p))}}
// 유저의 기준가격을 넘긴다면 이모티콘 플러스 가입시키기
if userSum >=user[1]{
cnt +=1}else{
sum += userSum
}}if cnt > emtiplusCnt {
emtiplusCnt = cnt
sumSale = sum
}elseif cnt == emtiplusCnt {
sumSale = sum > sumSale ? sum : sumSale
}}return[emtiplusCnt, sumSale]}func dfs(index:Int, arr:[Int], max:Int){if index == max {
percentArr.insert(arr)return}for_in0..<max {dfs(index: index +1, arr: arr +[10], max: max)dfs(index: index +1, arr: arr +[20], max: max)dfs(index: index +1, arr: arr +[30], max: max)dfs(index: index +1, arr: arr +[40], max: max)}}
// 이모티콘 할인 가격 계산
func calDiscountPrice(_ origin:Double, _ percent:Double)->Int{returnInt(origin -((origin /100)* percent))}- 이모티콘 할인율 조합을 구하는 dfs부분에서 문제가 있다고 판단했음
두번째 시도 - dfs 부분 불필요한 코드 제거 → 정답
- 최저 0.25 / 최고 3721.27
varpercentArr:[[Int]]=[]func solution(_ users:[[Int]], _ emoticons:[Int])->[Int]{letusers= users.sorted(by:{$0[0]>$1[0]})letsales=[10,20,30,40].filter({ $0 >= users.last![0]})
// 이모티콘의 할인가격 배열 구하기
dfs(index:0, arr:[], max: emoticons.count, sales: sales)varfinalEmtiPlusCnt=0varfinalSum=0forpercentinSet(percentArr){varemtiplusCnt=0varsum=0foruserin users {varuserSum=0for(index, p)in percent.enumerated(){
// 유저의 기준비율에 맞는 이모티콘만 선별하기
if p >=user[0]{
userSum +=calDiscountPrice(emoticons[index], p)}}
// 유저의 기준가격을 넘긴다면 이모티콘 플러스 가입
if userSum >=user[1]{
emtiplusCnt +=1}else{
sum += userSum
}}
// 현재 할인 비율 모음이 최대 이모티콘 플러스 가입자를 이끌어내는지 확인
if emtiplusCnt > finalEmtiPlusCnt {
finalEmtiPlusCnt = emtiplusCnt
finalSum = sum
}elseif emtiplusCnt == finalEmtiPlusCnt {
finalSum = sum > finalSum ? sum : finalSum
}}return[finalEmtiPlusCnt, finalSum]}func dfs(index:Int, arr:[Int], max:Int, sales:[Int]){if index == max {
percentArr.append(arr)return}forsalein sales {dfs(index: index +1, arr: arr +[sale], max: max, sales: sales)}}
// 이모티콘 할인 가격 계산
func calDiscountPrice(_ origin:Int, _ percent:Int)->Int{return origin -((origin /100)* percent)}
3중 중첩 for문을 제거하고 2중 for문으로 대체한 풀이.
dfs에서 조합을 구할 때마다 해당 할인가격 조합의 이모티콘플러스 가입자 수와 판매액이 최댓값인지 비교하기
varfinalEmtiPlusCnt=0varfinalSum=0varuser:[[Int]]=[]varemoticon:[Int]=[]func solution(users:[[Int]], emoticons:[Int])->[Int]{
user = users
emoticon = emoticons
dfs(index:0, arr:[], max: emoticons.count, sales:[10,20,30,40])return[finalEmtiPlusCnt, finalSum]}func dfs(index:Int, arr:[Int], max:Int, sales:[Int]){
// 이모티콘의 할인가격 조합 도출
if index == max {
// 해당 할인가격 조합의 이모티콘플러스 가입자 수와 판매액이 최댓값인지 비교
getResultBySalesComb(arr)return}forsalein sales {dfs(index: index +1, arr: arr +[sale], max: max, sales: sales)}}
// 이모티콘플러스 가입자 수와 판매액 도출 후 최댓값인지 비교하는 메서드
func getResultBySalesComb(_ arr:[Int]){varemtiplusCnt=0varsum=0foruin user {varuserSum=0for(index, p)in arr.enumerated(){
// 유저의 기준비율에 맞는 이모티콘만 선별
if p >=u[0]{
userSum +=calDiscountPrice(emoticon[index], p)}}
// 유저의 기준가격을 넘긴다면 이모티콘 플러스 가입
if userSum >=u[1]{
emtiplusCnt +=1}else{
sum += userSum
}}
// 현재 할인 비율 모음이 최대 이모티콘 플러스 가입자를 이끌어내는지 확인
if emtiplusCnt > finalEmtiPlusCnt {
finalEmtiPlusCnt = emtiplusCnt
finalSum = sum
}elseif emtiplusCnt == finalEmtiPlusCnt {
finalSum = sum > finalSum ? sum : finalSum
}}
// 이모티콘 할인 가격 계산 메서드
func calDiscountPrice(_ origin:Int, _ percent:Int)->Int{return origin -((origin /100)* percent)}dfs 부분 불필요한 코드 제거 && 고차함수 사용하여 비교군 감소
varfinalEmtiPlusCnt=0varfinalSum=0varuser:[[Int]]=[]varemoticon:[Int]=[]func solution(users:[[Int]], emoticons:[Int])->[Int]{
user = users.sorted(by:{$0[0]>$1[0]})
emoticon = emoticons
dfs(index:0, arr:[], max: emoticons.count, sales:[10,20,30,40].filter({ $0 >= user.last![0]}))return[finalEmtiPlusCnt, finalSum]}func dfs(index:Int, arr:[Int], max:Int, sales:[Int]){
// 이모티콘의 할인가격 조합 도출
if index == max {
// 해당 할인가격 조합의 이모티콘플러스 가입자 수와 판매액이 최댓값인지 비교
getResultBySalesComb(arr)return}forsalein sales {dfs(index: index +1, arr: arr +[sale], max: max, sales: sales)}}
// 이모티콘플러스 가입자 수와 판매액 도출 후 최댓값인지 비교하는 메서드
func getResultBySalesComb(_ arr:[Int]){varemtiplusCnt=0varsum=0foruin user {varuserSum=0for(index, p)in arr.enumerated(){
// 유저의 기준비율에 맞는 이모티콘만 선별
if p >=u[0]{
userSum +=calDiscountPrice(emoticon[index], p)}}
// 유저의 기준가격을 넘긴다면 이모티콘 플러스 가입
if userSum >=u[1]{
emtiplusCnt +=1}else{
sum += userSum
}}
// 현재 할인 비율 모음이 최대 이모티콘 플러스 가입자를 이끌어내는지 확인
if emtiplusCnt > finalEmtiPlusCnt {
finalEmtiPlusCnt = emtiplusCnt
finalSum = sum
}elseif emtiplusCnt == finalEmtiPlusCnt {
finalSum = sum > finalSum ? sum : finalSum
}}
// 이모티콘 할인 가격 계산 메서드
func calDiscountPrice(_ origin:Int, _ percent:Int)->Int{return origin -((origin /100)* percent)}
💬 문제[코딩테스트 연습 - 이모티콘 할인행사](https://school.programmers.co.kr/learn/courses/30/lessons/150368)
💬 Idea💬 풀이첫번째 시도 - 시간초과 [정확성 (75/100)]
두번째 시도 - dfs 부분 불필요한 코드 제거 → 정답
3중 중첩 for문을 제거하고 2중 for문으로 대체한 풀이.
dfs에서 조합을 구할 때마다 해당 할인가격 조합의 이모티콘플러스 가입자 수와 판매액이 최댓값인지 비교하기
dfs 부분 불필요한 코드 제거 && 고차함수 사용하여 비교군 감소