관리 메뉴

bright jazz music

다중 포인터 패턴 본문

Algorithm&Data structure/패턴 및 접근법(JS)

다중 포인터 패턴

bright jazz music 2024. 11. 23. 18:40

한 개의 포인터가 이동하며 조건에 부합하는 값을 찾는 것이 아니라 여러 개의 포인터를 사용하여 값을 찾아내는 방식

function sumZero(arr){
    for(let i = 0; i < arr.length; i++){
        for(let j = i+1; j < arr.length; j++){
            if(arr[i] + arr[j] === 0){
                return [arr[i], arr[j]];
            }
        }
    }
}


sumZero([-4,-3,-2,-1,0,1,2,5])
// 이렇게 하나의 포인터만 사용하여 값을 찾게되면 하나의 원소를 기준으로 n번을 돌아야 할 수도 있다.
// 입력 데이터가 크면 문제가 된다.

 

아래는 포인터를 투 개 사용한 투 포인터 방식이다. 포인터를 시작 지점과 끝 지점, 두 개를 사용하여 중앙을 향해 범위를 좁혀오는 방식이다. 단, 배열이 정렬돼 있어야 한다.

// 배열이 정렬돼 있어야함.
function sumZero(arr) {
    let left = 0;
    let right = arr.length - 1;
    while(left < right) {
        let sum = arr[left] + arr[right];
        if(sum === 0) {
            return [arr[left], arr[right]];
        } else if(sum > 0) {
            right--;
        } else {
            left++;
        }
    }
}

 

 

예제) 고윳값의 개수

다중 포인터 - countUniqueValues
정렬된 배열을 받아들이고 배열의 고유 값을 세는 countUniqueValues라는 함수를 구현합니다. 배열에 음수가 있을 수 있지만 항상 정렬됩니다.

countUniqueValues([1,1,1,1,1,2]) // 2
countUniqueValues([1,2,3,4,4,4,7,7,12,12,13]) // 7
countUniqueValues([]) // 0
countUniqueValues([-2,-1,-1,0,1]) // 4
Time Complexity - O(n)

Space Complexity - O(n)

보너스

상수 또는 O(1) space 와 O(n) time으로만 이 작업을 수행해야 합니다.

 

강의 듣고 내가 푼 답

// function countUniqueValues(arr){
//   return [...new Set(arr)].length;
// }

function countUniqueValues(arr) {
    
    const sortedArr = arr.sort((a, b) => a - b);
    
    if (arr.length === 0) return 0;
    
    let i = 0; 
    let j = 1;
    
    while( j < sortedArr.length) {
        if (sortedArr[i] === sortedArr[j]) {
            j++; 
        } else {
            
            i++;
            sortedArr[i] = sortedArr[j]
        }
    }
    
    return i+1; // 새로운 값을 할당한 자리의 인덱스는 개수보다 하나 작으므로 +1
}
// 포인터가 중앙을 향해 이동하는 것이 아니라 같은 방향으로 이동한다.
// 배열이 정렬돼 있지 않으면 같은 값이 인덱스를 달리하여 기록될 수 있으므로 정렬해야 한다.

 

강사 코드

function countUniqueValues(arr){
    if(arr.length === 0) return 0;
    var i = 0;
    for(var j = 1; j < arr.length; j++){
        if(arr[i] !== arr[j]){
            i++;
            arr[i] = arr[j]
        }
    }
    return i + 1;
}
countUniqueValues([1,2,2,5,7,7,99])

 

 

 

예제)

다중 포인터 - averagePair
averagePair라는 함수를 작성합니다. 정렬된 정수 배열과 목표 평균이 주어졌을 때, 배열에 쌍의 평균이 목표 평균과 같은 값의 쌍이 있는지 확인합니다. 목표 평균과 일치하는 쌍이 두 개 이상 있을 수 있습니다.

보너스 제약조건:

Time: O(N)

Space: O(1)

예시 인풋:

averagePair([1,2,3],2.5) // true
averagePair([1,3,3,5,6,7,10,12,19],8) // true
averagePair([-1,0,3,4,5,6], 4.1) // false
averagePair([],4) // false

 

내 풀이

function averagePair(sortedArr, avg){
    // 입력배열이 정렬돼 있다고 가정. 이 방법은 정렬돼 있어야 사용 가능하다.
    // 두 개를 더해 2로나눈 값이 avg보다 크다면 
    // right를 감소시킨다. 정렬돼 있으므로 더 작은 값이어야 나눈 값이 줄어들 테니까
    // 만약 값이 avg보다 작다면 left를 증가시킨다. 그래야 좀 더 커질 테니까

    let left = 0;
    let right = sortedArr.length -1;
    
    while ( left < right) {
        let dividedVal = (sortedArr[left] + sortedArr[right]) / 2
        if( dividedVal === avg) return true;
        
        if (dividedVal > avg) right--
        if (dividedVal < avg) left++
    }
    
    return false;
    
    
}
Comments