홍열 2021. 2. 1. 13:08
728x90

예전에 풀었던 2Sum에 이은 3Sum문제..

 

a + b + c = 0이 되는 조합을 출력하는 것이고, 중복 조합은 허락하지 않는다. 

중복을 허락하지 않으므로, set으로 결과 관리를 하면 될것 같음

n^3으로 풀릴것도 같다. 

 

1) 첫번째 도전 (for문 3번)

def threeSum(self, nums: List[int]) -> List[List[int]]:
        ans = []
        nums.sort()
        check = set()
        for i in range(len(nums)):
            for j in range(i+1, len(nums)):
                for k in range(j+1, len(nums)):
                    a, b, c, = nums[i], nums[j], nums[k]
                    if a+b+c == 0 and (a,b,c) not in check:
                        ans.append([a,b,c])
                        check.add((a,b,c))
        return ans

=> 결과는 Time Limit이다. 

 

n^3을 n^2으로 줄이는 방법을 생각해야된다. 

 

2) two sum에서 사용했던 방법중에 in을 사용하는 방법이 있었다. 

=> 결과는 틀린 답..중간에 자꾸 하나씩 답이 빠진다. 

=> sum값이 0일때 left, right를 하나씩 증가,감소시키는데, 그 다음에 답이 있는 경우에 문제가 생김

    def threeSum(self, nums):
        ans = []
        nums.sort()
        check = set()

        left, right = 0, len(nums)-1

        #2개 이하는 값을 만들 수 없으므로 빈 리스트
        if len(nums) < 3: return []


        while left<right:
            sum = nums[left] + nums[right]

            if sum == 0:
                if 0 in nums[left+1: right]:
                    tmp = [0, nums[left], nums[right]]
                    tmp.sort()
                    if tmp not in ans:
                        ans.append(tmp)
				left += 1
                right -= 1
            elif sum < 0:
                if (sum * -1) in nums[left+1: right]:
                    tmp = [sum*(-1), nums[left], nums[right]]
                    tmp.sort()
                    if tmp not in ans:
                        ans.append(tmp)
                left += 1
            elif sum > 0:
                if (sum * -1) in nums[left+1: right]:
                    tmp = [sum*(-1), nums[left], nums[right]]
                    tmp.sort()
                    if tmp not in ans:
                        ans.append(tmp)
                right -= 1
        print(ans)
        return ans

3) 기준을 하나로 두고, 나머지를 two pointer로 움직이는 방식

-> a+b+c = 0을 만들기 위해서는 최소 3개의 수가 필요하다. 

    for문도 n-2번까지만 돌면 된다

-> 중복 체크도 하면 시간이 더 줄어들 수 있다. (arr[i] == arr[i+1] 이면 continue)

-> 어렵다..이걸 다들 어떻게 푸냐..책보고 공부하는거지만 어려움

def threeSum(self, nums: List[int]) -> List[List[int]]:
        # 3개 이하는 조건이 성립이 안되므로 패스
        if len(nums) < 3: return []
        result = []
        # 정렬해서 구하도록 변경
        nums.sort()
        
        # 전체 크기의 -2까지만 돌리도록...
        for i in range(len(nums)-2):
            # 바로 전에 구한 값이므로 패스 
            if i>0 and nums[i] == nums[i-1]:
                continue
            
            # i라는 기준에서 i다음 것과 배열의 끝값을 기준으로 two pointer를 설정한다. 
            left, right = i+1, len(nums)-1 
            
            while left < right:
                sum = nums[i] + nums[left] + nums[right]
                
                if sum<0:
                    left+=1
                elif sum>0:
                    right-=1
                elif sum == 0:
                    # append시에 정렬되도록 순서대로 넣자
                    tmp = [nums[i], nums[left], nums[right]]
                    if tmp not in result:
                        result.append(tmp)
                    
                    # 같은 값이면 건너뛰도록...중복 허용하지 않는 방법
                    if left < right and nums[left] == nums[left+1]:
                        left+=1
                    elif left < right and nums[right] == nums[right-1]:
                        right-=1
                    left += 1
                    right -=1
        return result