coms1101   2년 전

정말 파이썬이 이렇게 느린 언어인가요...?

파이썬코드로는 통과되지 않았던 알고리즘이 코틀린으로 제출하니 풀리네요....

언어 마다 속도가 다르다지만 이런 알고리즘에서 같은 알고리즘인데 어떤 언어는 통과되고 어떤 언어는 통과가 안된다는게 조금 이해할 수가 없네요...

ps.

코틀린은 클래스에 맴버변수로 선언했고 파이썬은 그냥 함수의 매개변수로 전달해서 거기에서 속도차이가 날 수 있다라고 하실 수도 있어서 말하자면 파이썬에서도 클래스를 구현해서 맴버변수로 만들어서 제출해봤습니다. 정말 코틀린으로 작성한 코드와 언어의 유형만 다르다고 할 정도로 똑같이....

하지만 파이썬에서는 시간초과로 통과가 안되더라구요.....ㅠㅠㅠㅠ

이게 백준 사이트에서의 최적화 문제인 건가요...?

여러 언어로 문제를 풀 수 있다는 점은 좋지만 같은 알고리즘인데 언어가 다르다고 결과가 다른 점은 조금 아쉽네요.....


class Tree(var n: Int) {

private var graph: ArrayList<ArrayList<ArrayList<Int>>> = ArrayList<ArrayList<ArrayList<Int>>>()

private var visited: ArrayList<Boolean> = ArrayList<Boolean>()

private var leafNode: ArrayList<Int> = ArrayList<Int>()

init {

for(i in 0..this.n) {

this.graph.add(ArrayList<ArrayList<Int>>())

this.visited.add(false)

}

makeTree()

}

// 트리 만들기

private fun makeTree() {

for(i in 1 until this.n) {

var nodeWeight = readLine()!!.split(" ").map{ it.toInt() }

// 부모노드에 (자식노드, 가중치) 저장

var edge = arrayListOf(nodeWeight[1], nodeWeight[2])

this.graph[nodeWeight[0]].add(edge)

// 자식노드에 (부모노드, 가중치) 저장

edge = arrayListOf(nodeWeight[0], nodeWeight[2])

this.graph[nodeWeight[1]].add(edge)

}

// leafNode 만들기

for(i in 1..this.n) {

if(this.graph[i].size == 1) {

this.leafNode.add(i)

}

}

}

// 노드의 가장 먼 노드까지의 길이 구하기

private fun lineLength(node: ArrayList<Int>): Int {

// 현재 노드 방문 처리

this.visited[node[0]] = true

var length = 0

// 깊이 우선 탐색

for (i in this.graph[node[0]]) {

if(!this.visited[i[0]]) {

var tmp = i[1] + lineLength(i)

// 현재 구해진 길이보다 길다면 tmp 값으로 변경

length = if(length < tmp) tmp else length

}

}

return length

}

// 결과 구하기

fun getAnswer() {

var answer = 0

for(idx in this.leafNode) {

// 방문 처리 리스트

for(i in 0..this.n) {

this.visited[i] = false

}

// 시작노드 방문 처리

this.visited[idx] = true

// 시작노드에 연결된 노드 방향으로 길이 구하기

var length = graph[idx][0][1] + lineLength(graph[idx][0])

// 이전 길이보다 길경우 answer 값 변경

answer = if(answer < length) length else answer

}

println(answer)

}

}

fun main() {

var n: Int = readLine()!!.toInt()

var tree = Tree(n)

tree.getAnswer()

}

ai4youej   2년 전

빠른 입출력을 한 번 적용해보세요

coms1101   2년 전

빠른 입출력을 사용해도 결과는 동일했습니다.

파이썬에서 속도를 줄일 수 있다는 방법은 다 사용해봤던 것 같네요.....

shjohw12   2년 전

파이썬이 느린 것도 있지만 애초에 느린 풀이라서 그렇습니다. 정해로 풀면 파이썬으로도 수월하게 통과합니다.

ai4youej   2년 전

백준 서버는 충분히 좋은 서버입니다.

똑같은 알고리즘이라도 언어에 따라 퍼포먼스 차이는 충분히 많이 날 수 있고, 구현에 따라서도 날 수 있습니다. (캐시히트라던가...)

또한 상위 난이도의 문제로 가면 아예 C++이 반강제되는 경우도 많습니다

shiftpsh   2년 전

n = 10 000 인데 O(n2)라서 안타깝게도 2초라면 시간 안에 돌 수도 있고 안 돌 수도 있는 알고리즘이라고 생각합니다.

djm03178   2년 전

언어마다 속도가 현저히 다르고, 서로 빠르고 느린 부분이 다르며, 비슷한 로직이라도 실제로 어떤 연산들로 이루어져있느냐에 따라 큰 차이가 발생하는 것은 당연합니다. 파이썬은 이를 감안해서 다른 언어에 비해 훨씬 많은 시간 보너스를 제공하고 있습니다. 그럼에도 불구하고 파이썬이 다소 불리한 것은 사실입니다.

질문에 올려주신 코드는 시간 복잡도가 O(N^2)입니다. 이는 N의 제한이 최대 1만인 것과, 상수가 다소 크다는 점, 그리고 문제가 매우 오래됐다는 점을 감안하면 그다지 2초 내에 통과되기를 바라는 풀이가 아니라고 보입니다. 그럼에도 불구하고 요즘 컴퓨터가 너무 빨라져서 대다수의 언어에서 이런 풀이가 통과될 수 있을 뿐입니다. 설령 같은 풀이로 통과되지 않는 언어가 있다고 해도 문제의 시간 제한이 잘못되었다고 볼 수는 없습니다.

이 문제에는 O(N)의 풀이가 있습니다. 그런 풀이를 작성하신다면 파이썬으로도 아주 넉넉하게 통과될 수 있습니다.

coms1101   2년 전

이렇게 많은 댓글을 써주셔서 감사합니다!!!

정말 단지 궁금한 점이었는데 친절하게 답변해주셔서 감사합니다!!

풀이 자체가 느린 풀이는 맞지만 언어에 따라서 풀이가 통과가 되기도 하고 안되기도 한다는 점이 조금 아쉬워서 이렇게 푸념을 널어놓았네요....

계속해서 더 좋은 알고리즘을 공부찾아보는 공부를 해봐야겠어요.

많은 답변 감사합니다!!

댓글을 작성하려면 로그인해야 합니다.