leetcode刷题-二分查找&分治

·  阅读 647

leetcode刷题-二分查找&分治

1、在一个重复元素的数组中查找key的最左位置

var binarySearch(nums, key) {
	let left = 0, right = nums.length - 1;
  
  while(left < right) {
    let mid = Math.floor(left + (right - left) / 2);
    if (nums[mid] >= key) {
      right = mid;
    } else {
      left = mid + 1;
    }
  }
  
  return left;
}
复制代码

2、x 的平方根

实现 int sqrt(int x) 函数。

计算并返回 x 的平方根,其中 x 是非负整数。

由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。

var mySqrt = function(x) {
  if (x <= 1) return x;

  let left = 1, right = x;

  while(left <= right) {
    const mid = Math.floor(left + (right - left) / 2);
    const value = mid ** 2;

    if (value === x) {
      return mid;
    } else if (value > x) {
      right = mid - 1;
    } else {
      left = mid + 1;
    }
  }

  return right;
};
复制代码

3、寻找比目标字母大的最小字母

给你一个排序后的字符列表 letters ,列表中只包含小写英文字母。另给出一个目标字母 target,请你寻找在这一有序列表里比目标字母大的最小字母。

在比较时,字母是依序循环出现的。举个例子:

如果目标字母 target = 'z' 并且字符列表为 letters = ['a', 'b'],则答案返回 'a'

var nextGreatestLetter = function(letters, target) {
  const n = letters.length;
  if (target >= letters[n - 1]) {
    return letters[0];
  }

  let left = 0, right = n - 1;

  while(left <= right) {
    const mid = Math.floor(left + (right - left) / 2);
    if (letters[mid] > target) {
      right = mid - 1;
    } else {
      left = mid + 1;
    }
  }

  return letters[left];
};
复制代码

4、第一个错误的版本

你是产品经理,目前正在带领一个团队开发新的产品。不幸的是,你的产品的最新版本没有通过质量检测。由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的。

假设你有 n 个版本 [1, 2, ..., n],你想找出导致之后所有版本出错的第一个错误的版本。

你可以通过调用 bool isBadVersion(version) 接口来判断版本号 version 是否在单元测试中出错。实现一个函数来查找第一个错误的版本。你应该尽量减少对调用 API 的次数。

var solution = function(isBadVersion) {
  /**
     * @param {integer} n Total versions
     * @return {integer} The first bad version
     */
  return function(n) {
    let left = 0, right = n;

    while(left <= right) {
      const mid = Math.floor(left + (right - left) / 2);
      if (isBadVersion(mid)) {
        right = mid - 1;
      } else {
        left = mid + 1;
      }
    }

    return left;
  };
};
复制代码

5、寻找旋转排序数组中的最小值

已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,2,4,5,6,7] 在变化后可能得到: 若旋转 4 次,则可以得到 [4,5,6,7,0,1,2] 若旋转 7 次,则可以得到 [0,1,2,4,5,6,7] 注意,数组 [a[0], a[1], a[2], ..., a[n-1]] 旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], ..., a[n-2]] 。

给你一个元素值 互不相同 的数组 nums ,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的 最小元素 。

var findMin = function(nums) {
  let left = 0, right = nums.length - 1;

  while (left < right) {
    const mid = Math.floor(left + (right - left) / 2);
    if (nums[mid] > nums[right]) {
      left = mid + 1;
    } else {
      right = mid;
    }
  }

  return nums[left];
};
复制代码

6、 在排序数组中查找元素的第一个和最后一个位置

给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。

如果数组中不存在目标值 target,返回 [-1, -1]。

var searchRange = function(nums, target) {
  const left = findLeft(nums, target);
  const right = findLeft(nums, target + 1) - 1;
  if (left < nums.length && nums[left] === target) {
    return [left, right];
  }
  return [-1, -1];
};


function findLeft(nums, target) {
  const n = nums.length;
  if (target > nums[n - 1]) return n;

  let left = 0, right = nums.length - 1;

  while(left < right) {
    const mid = Math.floor(left + (right - left) / 2);
    if (nums[mid] >= target) {
      right = mid;
    } else {
      left = mid + 1;
    }
  }

  return right;
} 
复制代码

7、为运算表达式设计优先级

给定一个含有数字和运算符的字符串,为表达式添加括号,改变其运算优先级以求出不同的结果。你需要给出所有可能的组合的结果。有效的运算符号包含 +, - 以及 * 。

var diffWaysToCompute = function(expression) {
  const n = expression.length;
  const res = [];
  const value = Number(expression);
  if (!isNaN(value)) return [value];

  for (let i = 0; i < n; i++) {
    const char = expression[i];
    let leftArr = [], rightArr = [];
    if (char === '+' || char === '-' || char === '*') {
      leftArr = diffWaysToCompute(expression.substring(0, i));
      rightArr = diffWaysToCompute(expression.substring(i + 1, n));
    }

    for (let x of leftArr) {
      for (let y of rightArr) {
        switch(char) {
          case '+':
            res.push(x + y);
            break;
          case '-':
            res.push(x - y);
            break;
          case '*':
            res.push(x * y);
            break;
        }
      }
    }
  }

  return res;
};
复制代码
分类:
前端
标签: