LeetCode 2762. Continuous Subarrays(JAVA)

2024. 12. 16. 17:14·알고리즘/LeetCode

출처 : https://leetcode.com/problems/continuous-subarrays/description/?envType=daily-question&envId=2024-12-14

 

#문제

You are given a 0-indexed integer array nums. A subarray of nums is called continuous if:
Let i, i + 1, ..., j be the indices in the subarray. Then, for each pair of indices i <= i1, i2 <= j, 0 <= |nums[i1] - nums[i2]| <= 2.
Return the total number of continuous subarrays.
A subarray is a contiguous non-empty sequence of elements within an array.


0-인덱스 기반 정수 배열 nums가 주어집니다. nums의 부분 배열은 다음 조건을 만족할 때 **연속적(continuous)**이라고 합니다:
부분 배열의 인덱스를 i, i + 1, ..., j라고 할 때, 인덱스 쌍 i <= i1, i2 <= j에 대해 항상 0 <= |nums[i1] - nums[i2]| <= 2를 만족합니다.
연속적인 부분 배열의 총 개수를 반환하세요.
부분 배열은 배열 내에서 연속적인 비어 있지 않은 요소들의 시퀀스를 의미합니다.

접근 : Two Pointer 방식

nums가 아래와 같다고하자

nums 6 5 6 7 5 6 4 5 6

 

nums의 원소를 탐색하면서 최댓값과 최솟값을 갱신해나가면서 둘의 차이가 2를 초과하지않는 범위를 구하면

  0 1 2 3 4 5 6 7 8
nums 6 5 6 7 5 6 4 5 6
max 6 6 6 7 7 7 7    
min 6 5 5 5 5 5 4    
max - min 0 1 1 2 2 2 3    

nums[0] ~ nums[5]의 범위가 나온다. 길이가 n인 부분수열의 수는 n(n+1)/2 이므로 

 

nums[0:5] 의 부분수열은 6 * 7 / 2 = 21개가 된다.

 

이어서 nums[6:8] 의 부분수열을 구하면되는가? 아니다

7을 만나기 직전까지 좌측으로 탐색을 진행하고 우측으로 탐색을 진행해야한다.

  0 1 2 3 4 5 6 7 8
nums 6 5 6 7 5 6 4 5 6
max       7 6 6 4 6 6
min       4 4 4 4 4 4
max - min       3 2 2 3 2 2

즉 nums[6:8] 가 아닌 nums[4:8]의 부분 수열을 구해야한다.

 

여기서 주의해야할것은 중복된 범위를 처리해주어야한다. 현재예시로는 nums[0:5] 와 nums[4:8]의 중복범위인 nums[4:5]중복을 처리해주어야한다.

 

때문에 문제에서 요구하는 답을 구하기위해서는 (nums[0:5]의 부분수열) + (nums[4:8]의 부분 수열) - (nums[4:5] 의 부분 수열 ) 을 해주어야한다.

 

전체코드

class Solution {
    public long continuousSubarrays(int[] nums) {
        int left = 0,right = 0;
        long cnt =0;
        int min = nums[0];
        int max = nums[0];
        for ( right =0; right < nums.length; right++) {
            min = Math.min(min, nums[right]);
            max = Math.max(max, nums[right]);
            if(max - min > 2){
            	//차이가 2를 초과한다면 현재까지 범위의 부분수열의 수를 더해준다
                long len = right - left;
                cnt += (len*(len+1))/2;
                left = right;
                
                //min,max를 초기화
                min = nums[right];
                max = nums[right];
                
                //이전의 최댓값을 만나기 직전까지 왼쪽으로 확장
                while(left > 0 && Math.abs(nums[right] - nums[left - 1]) <= 2){
                    left--;
                    max = Math.max(max, nums[left]);
                    min = Math.min(min, nums[left]);
                }
                
                //중복되는 범위 차감
                if (left < right) {
                    len = right - left;
                    cnt -= (len * (len + 1)) / 2;
                }
            }
        }
        long len = right - left;
        cnt += (len*(len+1))/2;
        
        return cnt;
    }
}

 

 

 

 

'알고리즘 > LeetCode' 카테고리의 다른 글

LeetCode 768. Max Chunks To Make Sorted II(JAVA)  (0) 2024.12.19
LeetCode 1792. Maximum Average Pass Ratio(JAVA)  (0) 2024.12.17
LeetCode 2779. Maximum Beauty of an Array After Applying Operation(JAVA)  (1) 2024.12.11
LeetCode 2054. Two Best Non-Overlapping Events(JAVA)  (0) 2024.12.10
LeetCode 1760. Minimum Limit of Balls in a Bag(JAVA)  (3) 2024.12.09
'알고리즘/LeetCode' 카테고리의 다른 글
  • LeetCode 768. Max Chunks To Make Sorted II(JAVA)
  • LeetCode 1792. Maximum Average Pass Ratio(JAVA)
  • LeetCode 2779. Maximum Beauty of an Array After Applying Operation(JAVA)
  • LeetCode 2054. Two Best Non-Overlapping Events(JAVA)
shryoo
shryoo
shryoo 님의 블로그 입니다.
  • shryoo
    shryoo 님의 블로그
    shryoo
  • 전체
    오늘
    어제
    • 분류 전체보기 (79)
      • TIL (21)
      • 알고리즘 (57)
        • LeetCode (32)
        • 프로그래머스 (17)
        • 백준 (8)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    알고리즘
    백준
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
shryoo
LeetCode 2762. Continuous Subarrays(JAVA)
상단으로

티스토리툴바