Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

22-jung0115 #182

Open
wants to merge 22 commits into
base: main
Choose a base branch
from
Open

22-jung0115 #182

wants to merge 22 commits into from

Conversation

jung0115
Copy link
Member

@jung0115 jung0115 commented Oct 30, 2024

➡️ 문제 풀이

🔗 문제 링크

프로그래머스 | 브루트포스 - 점 찍기(Lv.2)

좌표평면을 좋아하는 진수는 x축과 y축이 직교하는 2차원 좌표평면에 점을 찍으면서 놀고 있습니다. 진수는 두 양의 정수 k, d가 주어질 때 다음과 같이 점을 찍으려 합니다.

  • 원점(0, 0)으로부터 x축 방향으로 ak(a = 0, 1, 2, 3 ...), y축 방향으로 bk(b = 0, 1, 2, 3 ...)만큼 떨어진 위치에 점을 찍습니다.
  • 원점과 거리가 d를 넘는 위치에는 점을 찍지 않습니다.

예를 들어, k가 2, d가 4인 경우에는 (0, 0), (0, 2), (0, 4), (2, 0), (2, 2), (4, 0) 위치에 점을 찍어 총 6개의 점을 찍습니다.

정수 k와 원점과의 거리를 나타내는 정수 d가 주어졌을 때, 점이 총 몇 개 찍히는지 return 하는 solution 함수를 완성하세요.

✔️ 소요된 시간

70분

✨ 수도 코드

이번 문제는 간단하지만 계속해서 오답이 나와서 힘들었던 문제입니다 🥲

image

우선 처음에는 a, b 값을 기준으로 이중 for문을 돌아 완전 탐색 하는 방식으로 구현했습니다
원점과 거리가 d보다 작아야 하기 때문에 a, b는 모두 0 이상, d 이하입니다

image

위처럼 도출된 부등식을 이용해 a, b 값에 1부터 d까지를 다 대입하고, 중간에 값이 초과하면 break 해줬습니다.

var answer: Long = 0
val dDivideK = d/k
val maxDistance = dDivideK * dDivideK
        
for(a: Int in 0..dDivideK) {
  for(b: Int in 0..dDivideK) {
    val distance = a * a + b * b
    if(distance <= maxDistance) {
      answer++
    }
    else break
  }
}

하지만 위처럼 이중 for문을 사용하니 시간초과가 발생했습니다...

그래서 시간을 단축시킬 수 있는 방법을 고민하다가,
(a * k)를 기준으로 for문을 돌면서 거리가 d 이하가 될 수 있는 (b * k)의 개수를 구해 누적해주는 방법을 생각해냈습니다

image

위처럼 도출되는 부등식을 이용해 b의 최대값을 구해주면 가능한 좌표쌍의 개수를 알 수 있습니다.

이렇게 수정을 했음에도 계속 오답이 나와서 결국 솔루션을 찾아봤는데...
기준이 되는 (a * k)의 자료형을 long으로 해줘야 모든 케이스를 통과할 수 있었습니다
(a * k)의 자료형을 long으로 해주려면 for문에서 시작값과 끝값을 long으로 바꾸고, 증감하는 수까지 long으로 바꿔줘야 했습니다...!

for (a in 0L..d.toLong() step(k.toLong()))

이렇게 모든걸 long으로 바꾸고나니 드디어 통과할 수 있었습니다 🥹

✅ 최종 코드

class Solution {
  fun solution(k: Int, d: Int): Long {
    var answer: Long = 0L
    val dSquare: Long = d.toLong() * d.toLong()

    for (a in 0L..d.toLong() step(k.toLong())) {
      val maxB: Long = Math.sqrt((dSquare - a * a).toDouble()).toLong() / k.toLong() + 1L
      answer += maxB
    }
    
    return answer
  }
}

📚 새롭게 알게된 내용

.

Copy link
Member

@janghw0126 janghw0126 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저도 생각보다 쉬운 문제인 줄 알고 접근했는데 이중 for문을 이용하였더니 당연하게 시간 초과가 나더라고요! 그래서 피타고라스를 이용해서 찍을 수 있는 점 x를 구하고 y의 최댓값을 구해주었더니 통과가 되었습니다.

def solution(k, d):
    answer = 0

    for x in range(0,d+1,k):
        j = int((d**2 - x**2)**0.5)
        answer += (j // k) + 1        
        
    return answer

다른 분들의 코드를 참고하면서 풀어나가니까 더욱 간결하게 문제를 해결할 수 있었던 것 같습니다!
덕분에 많이 배워갑니다😊

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants