二分+快慢指针 有序、无序数组找重复值

75 阅读1分钟

题目

image.png

  • 对于有序数组,通过二分查找,如果当前位置和它相邻位置相等则返回,如果不相等,当前位置的值能和索引相同(索引和值都从 0 开始),那说明左边没有重复值,如果小于索引值,那说明左边有重复值,进行二分
  • 对于无需数组,那么通过值跳往对应下标,循环这样的方式一定存在环,结论:通过快慢指针相遇后,快指针回到原点每次走1步,再次和慢指针相遇的点就是环的起始点
// 有序数组情况
function process(arr) {
  let left = 0,
    right = arr.length - 1;
  while (left < right) {
    let mid = left + ((right - left) >> 1);
    if (
      (mid + 1 < arr.length && arr[mid] === arr[mid + 1]) ||
      (m - 1 >= 0 && arr[mid - 1] === arr[mid])
    ) {
      return arr[mid];
      // 说明左边没用重复数字
    } else if (arr[mid] === mid) {
      left = mid + 1;
    } else {
      right = mid - 1;
    }
  }
}

// 无序数组情况
function process(arr) {
  let slow = arr[0];
  // 快指针一次跳两步
  let fast = arr[arr[0]];

  while (slow !== fast) {
    slow = arr[slow];
    fast = arr[arr[fast]];
  }

  // 结论:当相遇后,快指针从起始位置走1步,再次和慢指针相遇时的位置就是环的起始位置
  fast = 0;
  while (slow !== fast) {
    slow = arr[slow];
    fast = arr[fast];
  }
  return slow;
}