[leetcode]_面试题 17.11. 单词距离

1,093

题目

面试题 17.11. 单词距离

有个内含单词的超大文本文件,给定任意两个不同的单词,找出在这个文件中这两个单词的最短距离(相隔单词数)。如果寻找过程在这个文件中会重复多次,而每次寻找的单词不同,你能对此优化吗?

示例

输入:words = ["I","am","a","student","from","a","university","in","a","city"], word1 = "a", word2 = "student"
输出:1

题解

枚举+二分

这不是很简单,将第一个单词的位置记录到 indexs 数组中,并且知道数组单调递增,枚举第二个单词的位置 x,用二分法查找在 indexs 与 x 最近接近的值;求出所有值的最小值即为答案

代码如下:

var findClosest = function (words, word1, word2) {
  if (word1 === word2) return 0;
  const len = words.length;
  let indexs = [];
  for (let i = 0; i < len; i++) {
    if (words[i] === word1) indexs.push(i);
  }
  //console.log(indexs)
  let min = 100000;
  for (let i = 0; i < len; i++) {
    if (words[i] === word2) {
      min = Math.min(min, query(i));
    }
  }

  function query(x) {
    if (x < indexs[0]) {
      return indexs[0] - x;
    }
    if (x > indexs[indexs.length - 1]) {
      return x - indexs[indexs.length - 1];
    }
    let left = 0;
    let right = indexs.length - 1;
    let l = 0;
    let r = right;
    while (left < right) {
      const m = Math.floor((left + right) / 2);
      if (indexs[m] === x) return 0;
      if (indexs[m] < x) {
        l = m;
        left = m + 1;
      } else {
        r = m;
        right = m - 1;
      }
    }

    return Math.min(
      Math.abs(x - indexs[l]),
      Math.abs(x - indexs[left]),
      Math.abs(x - indexs[r])
    );
  }

  return min;
};

枚举

不需要记录第一个单词所有的位置,也不需要将第一个单词位置全部记录再去找第二个位置;在枚举过程中,记录两个单词最后一次出现的位置,两位置绝对值之差最小值即为所求

代码如下

var findClosest = function (words, word1, word2) {
  const len = words.length;
  let left = null;
  let right = null;
  let min = len;
  for (let i = 0; i < len; i++) {
    if (words[i] === word1) {
      left = i;
    }
    if (words[i] === word2) {
      right = i;
    }
    if (left !== null && right !== null) {
      min = Math.min(min, Math.abs(right - left));
    }
  }

  return min;
};