class Solution:
def search(self, nums: List[int], target: int) -> int:
def binary_search(left, right):
if left <= right:
mid = (left + right) // 2 #중간 인덱스
if nums[mid] < target: #타겟은 중앙의 오른쪽에 위치
return binary_search(mid + 1, right)
elif nums[mid] > target: #타겟은 중앙의 왼쪽에 위치
return binary_search(left, mid - 1)
else: #타겟이면
return mid
else:
return -1
return binary_search(0, len(nums) - 1)
class Solution:
def search(self, nums: List[int], target: int) -> int:
left, right = 0, len(nums) - 1
while left <= right:
mid = (left + right) // 2
if nums[mid] < target:
left = mid + 1
elif nums[mid] > target:
right = mid - 1
else:
return mid
return -1
import bisect
class Solution:
def search(self, nums: List[int], target: int) -> int:
#bisect모듈의 bisect_left(list, target)은 list에 target을 정렬순으로 삽입할때
#넣을 수 있는 위치 중 가장 왼쪽에 위치한 위치를 반환하는 함수
idx = bisect.bisect_left(nums, target)
if idx < len(nums) and nums[idx] == target:
return idx
return -1
import bisect
class Solution:
def search(self, nums: List[int], target: int) -> int:
try:
return nums.index(target)
except ValueError:
return -1
따라서 중앙의 위치를 구하는 풀이를 다음과 같이 수정한다.
class Solution:
def search(self, nums: List[int], target: int) -> int:
#특정 피벗을 기준으로 회전되 배열
#최솟값의 인덱스 = 특정 피벗
left, right = 0, len(nums) - 1
while left < right:
mid = left + (right - left) // 2
if nums[mid] < nums[right]: #최솟값은 mid인덱스 포함 왼쪽에 위치
right = mid
else: #nums[mid] >= nums[right]일때, 최솟값은 mid인덱스 오른쪽에 위치
left = mid + 1
pivot = left
#target값의 인덱스 찾기
left, right = 0, len(nums) - 1
while left <= right:
mid = left + (right - left) // 2
real_mid = (mid + pivot) % len(nums) #진짜 중앙값의 위치 (모듈로 연산)
if nums[real_mid] < target:
left = mid + 1
elif nums[real_mid] > target:
right = mid - 1
else:
return real_mid
return -1
class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
result = set()
for num1 in nums1:
for num2 in nums2:
if num1 == num2:
result.add(num1)
return result
import bisect
class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
#한쪽은 순서대로 탐색하고, 다른 쪽은 정렬해서 이진 검색으로 값을 찾으면
#시간복잡도 O(nlogn)이 됨
result = set()
nums2.sort() #이진 검색은 정렬 된 배열에서 사용해야함
for num1 in nums1:
idx = bisect.bisect_left(nums2, num1)
if idx < len(nums2) and num1 == nums2[idx]:
result.add(num1)
return result
class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
#양쪽 다 정렬하여 투 포인터로 풀이
nums1.sort()
nums2.sort()
result = set()
i, j = 0, 0 #각각 nums1,nums2의 포인터
while i < len(nums1) and j < len(nums2):
if nums1[i] < nums2[j]:
i += 1
elif nums1[i] > nums2[j]:
j += 1
else:
result.add(nums1[i])
i += 1
j += 1
return result
class Solution:
def twoSum(self, numbers: List[int], target: int) -> List[int]:
left, right = 0, len(numbers) - 1
while left < right:
if numbers[left] + numbers[right] < target:
left += 1
elif numbers[left] + numbers[right] > target:
right -= 1
else:
return left + 1, right + 1
class Solution:
def twoSum(self, numbers: List[int], target: int) -> List[int]:
for i, n in enumerate(numbers):
expected = target - n
left, right = 0, len(numbers) - 1
while left <= right:
mid = left + (right - left) // 2
if numbers[mid] < expected:
left = mid + 1
elif numbers[mid] > expected:
right = mid - 1
else:
#인덱스 다를 때
if i != mid:
return i + 1, mid + 1
#인덱스 같을 때, 양쪽옆에 있는 값 중 같은 값 있으면 그 인덱스를 return
if numbers[mid] == numbers[mid + 1]:
return i + 1, mid + 2
elif numbers[mid] == numbers[mid - 1]:
return i + 1, mid
else:
break #while문 빠져나오고 for문 다음 반복
import bisect
class Solution:
def twoSum(self, numbers: List[int], target: int) -> List[int]:
for i, n in enumerate(numbers):
expected = target - n
idx = bisect.bisect_left(numbers[i + 1:], expected)
if idx < len(numbers[i + 1:]) and numbers[i + idx + 1] == expected:
return i + 1, i +idx + 2
👉 실행 속도가 2510ms로 2초 이상 소요됨
👉 슬라이싱은 편리하고 빠른 모듈이지만, 무분별하게 남용하다 보면 속도 저하의 주범이 될 수 있음
👉 성능 개선 해야함
import bisect
class Solution:
def twoSum(self, numbers: List[int], target: int) -> List[int]:
for i, n in enumerate(numbers):
expected = target - n
nums = numbers[i + 1:]
idx = bisect.bisect_left(nums, expected)
if idx < len(nums) and numbers[i + idx + 1] == expected:
return i + 1, i +idx + 2
👉 풀이3에서 슬라이싱을 줄이기 위해 nums 변수에 한 번만 사용해 담아두는 형태로 개선함
👉 1128ms로 풀이3에 비해 2배가량 속도가 빨라졌지만 투 포인터에 비해 많이 느림
👉 조금 더 개선이 필요함
import bisect
class Solution:
def twoSum(self, numbers: List[int], target: int) -> List[int]:
for i, n in enumerate(numbers):
expected = target - n
idx = bisect.bisect_left(numbers, expected, i + 1)
if idx < len(numbers) and numbers[idx] == expected:
return i + 1, idx + 1
👉 bisect모듈의 기능을 활용하여 139ms로 속도 개선 성공
#case1
a = [x for x in range(100000000)]
print(id(a)) #4365568832
b = a
print(id(b)) #4365568832
#=>여기서 b변수는 a변수 객체를 참조만 하면 되기 때문에 둘은 동일한 ID를 갖고 있음
#case2
c = a[:]
print(id(c)) #4365788800
#=>여기서 c변수는 슬라이싱으로 할당했기때문에 객체 참조가 아닌 요소 전체,
#즉 1억개를 모두 복사하는 과정을 거침
class Solution:
def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
row, col = 0, len(matrix[0]) - 1 #matrix[row][col] 행, 렬
while row < len(matrix) and col >= 0:
if matrix[row][col] < target: #target보다 작을 때
row += 1
elif matrix[row][col] > target: #target보다 클 때
col -= 1
else: #target과 같을때
return True
return False
👉 파이썬 all(), any() 함수 사용하여 pythonic way로 풀이
class Solution:
def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
return any([target in row for row in matrix])