js解leetcode(73)-中等

1.删列造序

题目:

给定由 n 个字符串组成的数组 strs,其中每个字符串长度相等。

选取一个删除索引序列,对于 strs 中的每个字符串,删除对应每个索引处的字符。

比如,有 strs = ["abcdef", "uvwxyz"],删除索引序列 {0, 2, 3},删除后 strs 为["bef", "vyz"]。

假设,我们选择了一组删除索引 answer,那么在执行删除操作之后,最终得到的数组的元素是按 字典序(strs[0] <= strs[1] <= strs[2] ... <= strs[n - 1])排列的,然后请你返回 answer.length 的最小可能值。

思路:可以从前往后遍历采用枚举法。枚举每一个字符,判断所有字符串到当前位置的字符是否符合字典序,如果符合,那么遍历下一个位置;如果不符合,就要删除当前位置的字符,然后找下一个。在删除的时候可以累加得到每个字符串对应的新字符串

时间复杂度O(mn),空间复杂度O(mn)

/**
 * @param {string[]} strs
 * @return {number}
 */
const minDeletionSize = (A) => {
  const h = A.length;
  const w = A[0].length;
  let ans = 0;

  let cur = new Array(h).fill("");
  for (let j = 0; j < w; ++j) {
    const cur2 = [...cur];
    for (let i = 0; i < h; ++i) {
      cur2[i] += A[i][j];
    }

    if (isSorted(cur2)) {
      cur = cur2;
    } else {
      ans++;
    }
  }

  return ans;
};

const isSorted = (A) => {
  for (let i = 0; i < A.length - 1; i++) {
    if (A[i] > A[i + 1]) {
      return false;
    }
  }
  return true;
};

2.N天后的牢房

题目:

8 间牢房排成一排,每间牢房不是有人住就是空着。

每天,无论牢房是被占用或空置,都会根据以下规则进行更改:

如果一间牢房的两个相邻的房间都被占用或都是空的,那么该牢房就会被占用。
否则,它就会被空置。
(请注意,由于监狱中的牢房排成一行,所以行中的第一个和最后一个房间无法有两个相邻的房间。)

我们用以下方式描述监狱的当前状态:如果第 i 间牢房被占用,则 cell[i]==1,否则 cell[i]==0。

根据监狱的初始状态,在 N 天后返回监狱的状况(和上述 N 种变化)。

思路:枚举法。因为最两边的牢房肯定是空着的,所以第一天的状态其实才是初始状态。因为牢房数量是固定的,最多有2^6=64种可能,可以枚举全部的可能,然后计算循环的长度。之后对天数取余即可

时间复杂度O(1),空间复杂度O(1)

/**
 * @param {number[]} cells
 * @param {number} n
 * @return {number[]}
 */
var prisonAfterNDays = function(cells, n) {
  const l = cells.length;
  const dp = new Array(l).fill(0);

  const getList = (cells) => {
    dp[0] = 0;
    dp[l - 1] = 0;
    for (let i = 1; i < l - 1; i++) {
      dp[i] = cells[i - 1] === cells[i + 1] ? 1 : 0;
    }
    for (let i = 0; i < l; i++) {
      cells[i] = dp[i];
    }
  };
  n--;
  getList(cells);
  const init = dp.slice();
  getList(cells);
  let length = 1;

  while (init.join() !== dp.join()) {
    getList(cells);
    length++;
  }
  n = n % length;
  while (n--) {
    getList(init);
  }
  return dp;
};

3.二叉树的完全性检验

题目:

给定一个二叉树,确定它是否是一个完全二叉树。

百度百科中对完全二叉树的定义如下:

若设二叉树的深度为 h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。(注:第 h 层可能包含 1~ 2h 个节点。)

思路:按照层序遍历的方式,遍历节点。同时,记录每个节点的编号。对于根节点,编号是0,对于任意一个节点,编号为i,它的左节点编号为2*i,右节点编号为2*i+1.

所以,在层序遍历时,只需要判断编号关系即可。

每一层的编号,应当从0开始且连续。

最后,需要判断层数和节点数的关系。为什么?因为可能最左边的节点深度更深不止一层,所以在层序遍历时,记录当前层的节点数量和下一层的节点数量的关系。如果不等于2倍,说明该层有空节点,说明再往下就不能有子节点了。

时间复杂度O(n),空间复杂度O(2^h)

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {boolean}
 */
var isCompleteTree = function(root) {
  let stack = [root];
  let numbers = [0];
  let c = 0;
  while (stack.length) {
    const temp = [];
    const tempN = [];
    const l = stack.length;
    for (let i = 0; i < l; i++) {
      if (i === 0) {
        if (numbers[0] !== 0) return false;
      } else if (i !== l - 1 && numbers[i] - numbers[i + 1] !== -1) {
        return false;
      }
      const cur = stack[i];
      const curN = numbers[i];
      if (!cur) continue;
      temp.push(cur.left);
      tempN.push(curN * 2);
      temp.push(cur.right);
      tempN.push(curN * 2 + 1);
    }
    if (temp.length !== 2 * l) {
      c++;
    }
    stack = temp;
    numbers = tempN;
  }
  return c <= 2;
};

4.最大宽度坡

题目:

给定一个整数数组 A,坡是元组 (i, j),其中  i < j 且 A[i] <= A[j]。这样的坡的宽度为 j - i。

找出 A 中的坡的最大宽度,如果不存在,返回 0 。

思路:

形成坡度需要后一个元素比前一个元素大,所以按照值的大小排序,大小相同时,下标小的在前面。
这样,每一个元素都能与它之前的元素形成坡,所以依次遍历数组的成员,只需要记录当前成员与前面的最小下标之差,就是当前所能形成的最大坡度,然后更新结果,之后更新最小下标

时间复杂度O(nlogn),空间复杂度O(n)

/**
 * @param {number[]} A
 * @return {number}
 */
var maxWidthRamp = function(A) {
  A = A.map((i, index) => [i, index]);
  A.sort((a, b) => {
    if (a[0] !== b[0]) {
      return a[0] - b[0];
    }
    return a[1] - b[1];
  });
  let max = 0;
  let min = A[0][1];
  const l = A.length;
  for (let i = 1; i < l; i++) {
    max = Math.max(max, A[i][1] - min);
    min = Math.min(min, A[i][1]);
  }
  return max;
};

5.最小面积矩形

题目:

给定在 xy 平面上的一组点,确定由这些点组成的任何矩形的最小面积,其中矩形的边不一定平行于 x 轴和 y 轴。

如果没有任何矩形,就返回 0。

思路:

观察矩形,矩形的对角线总是长度相等的,所以两条线长度相等且中点相同,就能组成一个矩形。

遍历每一条线,计算中点和长度,以中点、长度作为key,任意一个短点作为值,然后计算可以形成矩形的线条,计算面积的最小值

时间复杂度O(n3),空间复杂度O(n2)

/**
 * @param {number[][]} points
 * @return {number}
 */
const getmid = (x1, x2) => {
  return [(x1[0] + x2[0]) / 2, (x1[1] + x2[1]) / 2];
};
const getLength = (x1, x2) => {
  return Math.pow(x1[0] - x2[0], 2) + Math.pow(x1[1] - x2[1], 2);
};
var minAreaFreeRect = function (points) {
  const l = points.length;
  const map = new Map();
  let min = Infinity;
  for (let i = 0; i < l - 1; i++) {
    for (let j = i + 1; j < l; j++) {
      const middle = getmid(points[i], points[j]);
      const length = getLength(points[i], points[j]);
      if (map.has(`${middle[0]}-${middle[1]}-${length}`)) {
        const target = map.get(`${middle[0]}-${middle[1]}-${length}`);
        min = Math.min(
          min,
          ...target.map((item) => {
            return getLength(item, points[i]) * getLength(item, points[j]);
          })
        );
        map
          .get(`${middle[0]}-${middle[1]}-${length}`)
          .push(points[i]);
      } else {
        map.set(`${middle[0]}-${middle[1]}-${length}`, [points[i]]);
      }
    }
  }
  return min === Infinity ? 0 : Math.sqrt(min);
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值