nums
: 입력되는 배열 ()
이진수가 담긴 배열 array
에서 1개의 요소를 반드시 삭제해야 할 때 오직 1만 있는 가장 길고 빈칸이 없는 Substring의 크기를 반환하는 문제이다.
배열 전체를 확인하면서 1로 연속된 부분 배열의 최장 길이를 빠르게 찾아야 한다.
→ 슬라이딩 윈도우 활용
📖 슬라이딩 윈도우
- 배열에서 연속된 부분을 효율적으로 다루는 방법
- 진행 과정
- 2개의 포인터(left, right)로 구간 정하기
- 조건 따라 윈도우 사이즈 확장 또는 축소
- 사용 경우
- 에 해당하는 중첩 루프 → 하나의 루프로 최적화할 때 많이 사용
- 최대(최소) 합 가진 부분 합, 길이 k의 구간, 연속된 1/0의 최대 길이 등
- 연속이란 조건이 있다면 높은 확률로 사용 가능
구현
배열 내에서 슬라이딩 윈도우 →
최종 시간복잡도
이므로 충분히 동작할 수 있다.
nums
에서 숫자 하나씩 확인하면서 1인지 0인지 등의 경우에 따라 |
를 넣어서 1로만 이루어진 substring을 만들어보려고 했으나 고려해야 할 부분이 너무 많아서 구현하지 못했다.class Solution:
def longestSubarray(self, nums: List[int]) -> int:
# 윈도우 왼쪽 인덱스
left = 0
# 윈도우 내 0의 개수
count_0 = 0
# 최장 길이
max_len = 0
# 윈도우 오른쪽을 옮기면서 탐색
for right in range(len(nums)):
# 0이면 개수 증가
if nums[right] == 0:
count_0 += 1
# 윈도우 내 0이 2개 이상이면 0이 하나 남을 때까지 left 움직임
while count_0 > 1:
# 0인 경우 개수 줄이기
if nums[left] == 0:
count_0 -= 1
# left 움직이기
left += 1
# 현재 윈도우 길이 중 최댓값 갱신
max_len = max(max_len, right - left)
return max_len
class Solution:
def longestSubarray(self, nums: List[int]) -> int:
# 배열에 1만 있을 경우
if sum(nums) == len(nums):
return(len(nums)-1)
# 배열에 0만 있을 경우
if sum(nums) == 0:
return(0)
# 0이 있는 인덱스를 모두 저장하는 리스트 정의
locs = []
# 0이 있는 인덱스 저장
for i in range(len(nums)):
if nums[i] == 0:
locs.append(i)
# 0이 하나면 그것만 제거한 길이 반환
if len(locs) == 1:
return(len(nums)-1)
# 0이 여러 개 라면
# 첫 번째 연속 구간 길이(첫번째 0과 두번째 0 사잉의 1로 이루어진 구간 길이) 계산
size = locs[1] - 0 - 1
# 최장 길이 초기화
max_size = size
# 여러 0 사이 구간 탐색
# 두 번째 0부터 끝까지 하나씩 이동해 구간 계산
if len(locs) > 2:
for i in range(2, len(locs)):
# 인덱스 기준으로 거리 조정하며 0 제거
size = locs[i] - locs[i-2] - 1 - 1
max_size = max(size, max_size)
# 마지막 0 이후로 남은 연속된 1 구간 길이 확인
if locs[-1] < len(nums)-1:
size = len(nums)-1 - locs[-2] - 1
max_size = max(size, max_size)
return(max_size)