알고리즘 문제 풀이

[Swift] BOJ 7453 합이 0인 네 정수

lgvv 2022. 5. 12. 18:35

BOJ 7453 합이 0인 네 정수

 

✅ 와 진짜 하루종일 풀어도 안풀렸다.

이진 탐색 분야인데 이게 개념은 늘 그냥 하면 되는거지 싶었는데, 막상 적용하려니까 엄청나게 어렵다.

 

✅ 알고리즘 접근법 

이 문제의 경우에는 시간 제한이 있기 때문에, 다중 for문과 contains로는 해결할 수 없다.

 

1. input과정에서 column을 4개를 만들어서 따로 받는다.

2. col 1,2 그리고 col3,4를 for문으로 더해서 나올 수 있는 케이스를 구한다. (sumAB, sumCD)

3. sumAB와 sumCD를 정렬한다.(나는 오름차순으로 정렬)

4. [핵심]

 sumAB는 앞 부분부터 sumCD는 뒤 부분부터 순회하면서 값을 비교합니다.

 -> 왜냐하면 가장 작은 값과 가장 큰 값의 합이어야 0이 나올 수 있기 때문에.

 

1. sumAB의 값과 sumCD에서 참조한 값의 합이 0일 경우

 

이 경우에는 result를 하나 올려줍니다. 근데 여기서 유의할 점이 있습니다.

sumAB = [-3, -3, -3, 2, 5 ,7]

sumCD = [-5,-3, 1, 2, 3, 3] 

이런식으로 중복이 있는 경우입니다.

 

이 경우에는 sumAB에서 -3의 갯수만큼 sumCD에서 3의 갯수만큼을 찾습니다.

그리고 각각에서 나온 갯수를 곱한 만큼 경우의 수가 만들어지므로 이 값을 result에 반영합니다.

 

 

2. sumAB의 값과 sumCD에서 참조한 값의 합이 0보다 작은 경우

이 경우에는 left의 값을 1증가시켜 줍니다.

너무 큰값이 들어있거나 혹은, 너무 작은 값이 들어있기 때문인데, 이건 자유롭게 설정하면 됩니다.

 

3. sumAB의 값과 sumCD에서 참조한 값의 합이 0보다 큰 경우

위와 동일한 논리에서 right의 값을 1 감소시켜 줍니다.

 

 

        let n = Int(readLine()!)!
        
        var a = [Int64]()
        var b = [Int64]()
        var c = [Int64]()
        var d = [Int64]()
        
        for _ in 0..<n {
            let temp = readLine()!.split(separator: " ").map { Int64(String($0))! }
            a.append(temp[0])
            b.append(temp[1])
            c.append(temp[2])
            d.append(temp[3])
        }
        
        var sumAB = [Int64]()
        var sumCD = [Int64]()
        
        for i in 0..<n {
            for j in 0..<n {
                sumAB.append(a[i] + b[j])
                sumCD.append(c[i] + d[j])
            }
        }
        
        sumAB.sort()
        sumCD.sort()
        
        var result: Int64 = 0
        var left = 0
        var right = sumAB.count - 1
        
        while left < sumAB.count && right >= 0 {
            let sum = sumAB[left] + sumCD[right]
            
            if sum == 0 { // 같을 경우
                // 중복이 몇개 있는지 체크합니다.
                var xCount: Int64 = 0
                var yCount: Int64 = 0
                let x = sumAB[left], y = sumCD[right]
                
                while sumCD[right] == y {
                    yCount += 1
                    right -= 1
                    if right == -1 { break } // right가 인덱스의 범위를 벗어남
                }
                
                while sumAB[left] == x {
                    xCount += 1
                    left += 1
                    if left == sumAB.count { break } // left가 인덱스의 범위를 벗어남
                }
                
                result += xCount * yCount
                
            } else if sum < 0 {
                left += 1
            } else {
                right -= 1
            }
        }
        
        print(result)

 

 

(참고)

https://github.com/lunchScreen/Problem_Solving/blob/main/%EA%B9%80%EB%91%90%EC%97%B0/swift/Baekjoon_7453.swift

 

GitHub - lunchScreen/Problem_Solving: 알고리즘을 공부하는 버디들

알고리즘을 공부하는 버디들. Contribute to lunchScreen/Problem_Solving development by creating an account on GitHub.

github.com

https://yabmoons.tistory.com/290

 

[ 백준 7453 ] 합이 0인 네 정수 (C++)

백준의 합이 0인 네 정수(7453) 문제이다. [ 문제 바로가기 ] [ 문제풀이 ] 1) 먼저 이 문제를 해결하는 가장 쉬운 방법은 4중 for문을 통해서 하나하나 모든 원소를 다 체크하면서 계산을 해주면   정

yabmoons.tistory.com