[알고리즘]Leetcode-배열

두 수의 합(Two Sum)

  • 덧셈하여 타겟을 만들 수 있는 배열의 두 숫자 인덱스를 리턴하라
  • 입력
    nums = [2, 7, 11, 15], target = 9
  • 출력
    [0, 1]
  • 풀이 : 첫번째 수를 뺀 결과 키 조회
    class Solution:
      def twoSum(self, nums: List[int], target: int) -> List[int]:
          nums_map = {}
            
          for i, num in enumerate(nums):
              # 2) 타겟에서 첫 번째 수를 뺀 결과를 키로 조회
              if target - num in nums_map:
                  return [nums_map[target - num], i]
              # 1) 키와 값을 바꿔서 딕셔너리로 저장
              nums_map[num] = i
    

빗물 트래핑(Trapping Rain Water)

  • 높이를 입력 받아 비 온 후 얼마나 많은 물이 쌓일 수 있는지 계산하라. image
  • 입력
    [0,1,0,2,1,0,1,3,2,1,2,1]
  • 출력
    6
  • 풀이 1) 투 포인터 이동 (64ms)
    class Solution:
      def trap(self, height: List[int]) -> int:
          if not height:
              return 0
            
          volume = 0
          left, right = 0, len(height) - 1
          left_max, right_max = height[left], height[right]
            
          while left < right:
              left_max, right_max = max(height[left], left_max), max(height[right], right_max)
                
              # 더 높은 쪽을 향해 투 포인터 이동
              if left_max <= right_max:
                  volume += left_max - height[left]
                  left += 1
              else:
                  volume += right_max - height[right]
                  right -= 1
            
          return volume
    
  • 풀이 2) 스택 (43ms)
    class Solution:
      def trap(self, height: List[int]) -> int:
          stack = []
          volume = 0
            
          for i in range(len(height)):
              # 변곡점(현재높이가 이전 높이보다 높을때) 만나는 경우
              while stack and height[i] > height[stack[-1]]:
                  # 스택에서 꺼냄
                  top = stack.pop()
                    
                  if not len(stack):
                      break;
                    
                  # 이전과의 차이만큼 물 높이 처리 
                  distance = i - stack[-1] - 1 
                  waters = min(height[i], height[stack[-1]]) - height[top]
                  volume += distance * waters
                
              stack.append(i)
          return volume
    

세 수의 합 (3Sum)

  • 배열을 입력받아 합으로 0을 만들 수 있는 3개의 엘리먼트를 출력하라
  • 입력
    nums = [-1, 0, 1, 2, -1, -4]
  • 출력
      [-1, 0, 1],
      [-1, -1, 2]
    ]
    
  • 풀이 : 투 포인터
    class Solution:
      def threeSum(self, nums: List[int]) -> List[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 < 0:
                      left += 1
                  elif sum > 0:
                      right -= 1
                  else:
                      results.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
    

배열 파티션 I (Array Partition I)

  • n개의 페어를 이용한 min(a, b)의 합으로 만들 수 있는 가장 큰 수를 출력하라
  • 입력
    [1,4,3,2]
  • 출력
    4
  • 설명
    n은 2가 되며, 최대 합은 4이다. min(1,2) + min(3, 4) = 4
  • 풀이 : 오름차순 짝수번째 계산하기
    class Solution:
      def arrayPairSum(self, nums: List[int]) -> int:
          return sum(sorted(nums)[::2]) # 두칸씩 건너뛰어 짝수 보기 
    

자신을 제외한 배열의 곱 (Product of Array Except Self)

  • 배열을 입력받아 output[i]가 자신을 제외한 나머지 모든 요소의 곱셈 결과가 되도록 출력하라
  • 입력
    [1,2,3,4]
  • 출력
    [24,12,8,6]
  • 주의 : 나눗셈을 하지 않고 O(n)에 풀이하라
  • 풀이 : 왼쪽 곱셈 결과에 오른쪽 값을 차례대로 곱셈
    class Solution:
      def productExceptSelf(self, nums: List[int]) -> List[int]:
          out = []
          p = 1
          # 왼쪽 곱셈 
          for i in range(0, len(nums)):
              out.append(p)
              p = p * nums[i]
          p = 1
          # 왼쪽 곱셈 결과에 오른쪽 값을 차례대로 곱셈 
          for i in range(len(nums) - 1, 0 - 1, -1):
              out[i] = out[i] * p
              p = p * nums[i]
          return out
    

주식을 사고팔기 가장 좋은 시점 (Best Time to Buy and Sell Stock)

  • 한 번의 거래로 낼 수 있는 최대 이익을 산출하라
  • 입력
    [7,1,5,3,6,4]
  • 출력
    5
  • 설명 : 1일때 사서 6일때 팔면 5의 이익을 얻는다.
  • 풀이 : 저점과 현재 값과의 차이 계산
    • 현재값을 가리키는 포인터가 우측으로 이동하면서 이전의 저점을 기준으로 가격 차이 계산 후, 클 경우 최댓값을 계속 교체
    • idea) 최댓값은 최솟값으로, 최솟값은 최댓값으로 지정 => 교체될 수 있도록
       class Solution:
        def maxProfit(self, prices: List[int]) -> int:
        profit = 0 
        min_price = sys.maxsize
              
        # min과 max를 계속 갱신
        for price in prices:
            min_price = min(min_price, price)
            profit = max(profit, price - min_price)
              
        return profit
      

카테고리:

업데이트: