Multiple pointer

no-pla·2024년 5월 2일
0
post-thumbnail

멀티 포인터 패턴은 정렬된 배열에서 한 쌍을 검색하는 데에 효과적인 패턴이다. 이 패턴은 인덱스나 위치에 해당하는 포인터 혹은 값을 만든 후 특정 지점으로 이동시킨다. 한 쌍의 값이나 조건을 충족시키는 무언가를 찾기 위한 패턴이다.

정렬된 배열에서 두 가지 숫자를 받아와, 0이 되는 값을 찾는 로직을 작성하기 위해서는 일반적으로 2중 루프를 사용할 수 있지만, 마찬가지로 시간 복잡도 면에서 좋지 않다.

다중 포인터 패턴을 사용해 보자.


const sumZero = (arr) => {
  let left = 0; // 포인터 1
  let right = arr.length -1; // 포인터 2
  
  while(left <= right) { // 같은 값을 가리키면 stop
    let sum = arr[left] + arr[right]; // 가리킨 값의 합
    if(sum === 0) {
    	return [arr[left], arr[right]];
    } else if(sum > 0) { // 정렬되어 있으므로 합한 값이 0 이상이면 큰 값(right)을 줄임
    	right--;
    } else {
    	left--;
    }
  }
  
}

sumZero([-3, -2, -1, 0, 1, 2, 3]);
sumZero([-2, 0, 1, 3]);
sumZero([1, 2, 3]);

위의 예시처럼 포인터를 두 개를 설정하고 두 값을 비교하면, 이중 반복문 사용 없이 원하는 답을 구할 수 있다.

이러한 패턴으로 중복되지 않은 값이 몇 개가 되는지 직접 작성해 본 코드는 다음과 같다.

function countUniqueValues(arr) {
  let i = 0;
  let j = 1;
  let answer = 0;

  while (j <= arr.length) {
    if (arr[i] !== arr[j]) {
      i = j;
      j++;
      answer++;
    } else if (arr[i] === arr[j]) {
      j++;
    }
  }

  return answer;
}

console.log(countUniqueValues([1, 1, 1, 1, 1, 1, 2])); // 2
console.log(countUniqueValues([1, 2, 3, 4, 4, 4, 7, 7, 12, 12, 13])); // 7
console.log(countUniqueValues([])); // 0
console.log(countUniqueValues([-2, -1, -1, 0, 1])); // 4

i와 j로 각각 두 인덱스를 가리킨다. 만약 두 값이 같은 값이면 다른 값이 나올 때까지 j에 숫자를 더해준다. 만약 같은 값일 경우, i에 j를 넣고, j에 숫자를 더한다. 이런 식으로 j가 배열의 길이와 일치할 때까지 더해준다.

이 패턴대로 하면 이중 루프를 사용할 필요가 없기 때문에 시간복잡도가 낮아지는 효과적인 코드를 작성할 수 있다.

0개의 댓글