[Python] Leetcode 1. 두 수의 합 구하기


Leetcode 1 Two Sum

문제

입력

nums = [2, 7, 11, 15] target = 9

출력

[0, 1]

풀이

1. 브루트 포스

  • 시간복잡도 : O(N^2)
def twoSum(self, nums: List[int], target: int) -> List[int]:
    for i in range(len(nums)-1):
        for j in range(i, len(nums)):
            if nums[i]+nums[j]==target:
                return [i, j]

2. 첫 번째 수를 뺀 결과 키 조회

  • 시간복잡도 : 평균 O(1), 최악 O(N)
def twoSum(self, nums: List[int], target: int) -> List[int]:
    nums_map = {}
    # 키와 값을 바꿔서 딕셔너리 저장
    for i, num in enumerate(nums):
        nums_map[num] = i

    # 타겟에서 첫 번째 수를 뺀 결과를 키로 조회
    for i, num in enumerate(nums):
        if target - num in nums_map and i != nums_map[target - num]:
            return nums.index(num), nums_map[target - num]

3. 투 포인터 이용

  • 시간복잡도 : 정렬 O(NlogN), 포인터 이동 및 계산 O(N)
  • 왼쪽 포인터와 오른쪽 포인터의 합이 타겟보다 크다면 오른쪽 포인터를 왼쪽으로, 작다면 왼쪽 포인터를 오른쪽으로 옮긴다. 정렬이 된 상태를 전제로 함.
  • 인덱스를 찾아내는 문제라면 인덱스 정보도 미리 저장해야한다.
def twoSum(self, nums: List[int], target: int) -> List[int]:
    nums.sort()
    left, right = 0, len(nums)-1
    while not left == right:
        if nums[left] + nums[right] > target:
            right -= 1
        elif nums[left] + nums[right] < target:
            left += 1
        else:
            return left, right


세수의 합 구하기

  • 마찬가지 방법으로 세수의 합 구하기 문제를 풀어보자
  • 세수의 합이 0인 경우를 출력해보자

입력

nums = [-1, 0, 1, 2, -1, -4] target = 0

출력

[
    [-1, 0, 1],
    [-1, -1, 2]
]

풀이

1. 브루트 포스

  • 시간복잡도 : O(N^3)
def twoSum(self, nums: List[int], target: int) -> List[int]:
    results = []
    nums.sort()
    for i in range(len(nums)-2):
        # 중복값 건너뛰기
        if i>0 and nums[i] == nums[i-1]:
            continue
        for j in range(i+1, len(nums)-1):
            if j>i and nums[j] == nums[j-1]:
                continue
            for k in range(j+1, len(nums)):
                if k > j+1 and nums[k] == nums[k-1]:
                    continue
                if nums[i]+nums[j]+nums[k]==target:
                    results.append((nums[i], nums[j], nums[k]))
    return results

2. 투 포인터 이용

  • 시간복잡도 : 정렬 O(NlogN), 포인터 이동 및 계산 O(N), 각 값마다 투 포인터 이동을 적용해야하므로 최종 시간복잡도 O(N^2)
def twoSum(self, nums: List[int], target: int) -> List[int]:
    results = []
    nums.sort()
    for i in range(len(nums)-2):
        # 중복된 값 건너뛰기
        if i > 0 and nums[i] == nums[i-1]:
            continue
        # 간격을 좁혀가며 합 sum계산
        left, right = i + 1, len(nums) - 1
        while left < right:
            sum = nums[i] + nums[left] + nums[right]
            if sum < target:
                left += 1
            elif sum > target:
                right -= 1
            else:
                # sum = target인 경우에는 정답 및 스킵처리
                reuslts.append((nums[i], nums[left], nums[right]))
                while left < right and nums[left] == nums[left+1]:
                    left += 1
                while left < right and nums[right] == nums[right-1]:
                    right -= 1
                # 그 다음부터 다시 시작
                left += 1
                right -= 1
    return results