알고리즘

알고리즘 - 배열을 비교할 때 사용하는 알고리즘

Okguri 2022. 5. 31. 20:50

배열 2개를 비교할 때 - Frequency Counter

배열 2개를 비교하는 작업에서 중첩 for문으로 비교하는 방법도 있지만, 성능면으로는 for문을 3번 반복하는 것이 훨씬 나음. O(n^2)보다 O(n)이 성능적으로 훨씬 낫기 때문. 

특히 JS의 경우 배열/문자열을 비교할 때 객체로 만들어서 사용하면 매우 편리함. 두 개의 배여를 객체로 세분화해 각 배열을 비교할 수 있음.

function same(arr1, arr2) {
  //배열 길이가 같지 않을 때 return false
  if (arr1.length !== arr2.length) {
    return false;
  }
  let frequencyCounter1 = {};
  let frequencyCounter2 = {};
  //arr 객체화. 원소(key) : 개수(value)
  for (let val of arr1) {
    frequencyCounter1[val] = (frequencyCounter1[val] || 0) + 1;
  }
  for (let val of arr2) {
    frequencyCounter2[val] = (frequencyCounter2[val] || 0) + 1;
  }
  console.log(frequencyCounter1);
  console.log(frequencyCounter2);

  for (let key in frequencyCounter1) {
    // arr1 원소 ^ 2가 arr2에 없을 때 false 반환
    if (!(key ** 2 in frequencyCounter2)) {
      console.log(key ** 2);
      return false;
    }
    // arr2와 arr1의 원소 개수 체크. ex) arr1에서 2가 2개 있을 때 arr2에서도 4가 2개 있어야 함. 같지 않을 경우 false 반환
    if (frequencyCounter2[key ** 2] !== frequencyCounter1[key]) {
      return false;
    }
  }
  return true;
}

Mutiple Pointer

인덱스/위치 등을 기준으로 포인터를 만들어 시작or끝지점, 양쪽 지점으로 이동시키는 것.

배열이나 문자열 같은 선형 구조에서 자주 쓰인다.

한쌍의 값을 찾을 때 유용하게 쓰인다.

example : 배열에서 두 원소 값이 0이 되는 첫 번째 한 쌍을 return */

function sumZero(arr) {
  //조건 : 오름차순 정렬일 때
  let sortedArr = arr.sort(function (a, b) {
    return a - b;
  });

  console.log(sortedArr);

  let left = 0; //배열의 첫 번째 idx
  let right = sortedArr.length - 1; //배열의 마지막 idx

  while (left < right) {
    let sum = sortedArr[left] + sortedArr[right];
    //합계가 0일 때 해당 쌍 반환
    if (sum === 0) {
      return [sortedArr[left], sortedArr[right]];
    }
    //둘의 합이 0이 넘으면 맨끝 idx에서 왼쪽으로 한 칸 이동
    else if (sum > 0) {
      right--;
    }
    //둘의 합이 0보다 작으면 맨 처음 idx에서 오른쪽으로 한 칸 이동
    else {
      left++;
    }
  }
}

sumZero([-4, -3, -52, 41, 0, 1, 2, 3, 10]);