js解leetcode(46)-中等

1.求解方程

题目:

求解一个给定的方程,将x以字符串"x=#value"的形式返回。该方程仅包含'+',' - '操作,变量 x 和其对应系数。

如果方程没有解,请返回“No solution”。

如果方程有无限解,则返回“Infinite solutions”。

如果方程中只有一个解,要保证返回值 x 是一个整数。

思路:提取方程中的x因子和整数运算,然后进行算术的运算,求解

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

/**
 * @param {string} equation
 * @return {string}
 */
var solveEquation = function(equation) {
    equation = equation.split('=');
    let cs = 0,
        bl = 0,
        flag = 0,
        ind = 0,
        one = equation[0].split(/[+-]/),
        two = equation[1].split(/[+-]/);
        if(one[0].length == 0) one.shift();
        if(two[0].length == 0) two.shift();
        if(equation[0][0] != '-') equation[0] = '+' + equation[0];
        if(equation[1][0] != '-') equation[1] = '+' + equation[1];
        
    function docal(equation,f,ot){
        ind = 0;
        for(let i = 0;i < equation.length; i++){
                if(equation[i] == '+' || equation[i] == '-'){
                    equation[i] == '-' ? flag = -1 * f : flag = 1 * f;
                    if(ot[ind][ot[ind].length-1]=='x'){
                        bl += ot[ind].length > 1 ? 
                        ot[ind].substring(0,ot[ind].length-1)*flag :
                        1 * flag;
                    }else{
                        cs += ot[ind]*flag;
                    }
                    ind++;
                } 
            }
        }
    docal(equation[0],1,one);
    docal(equation[1],-1,two);
    if(bl == 0 && cs == 0) return "Infinite solutions";
    if(bl == 0) return "No solution";
    let res = cs/bl * -1;
    return "x="+res.toString();
};

2.设计循环双端队列

题目:

设计实现双端队列。
你的实现需要支持以下操作:

MyCircularDeque(k):构造函数,双端队列的大小为k。
insertFront():将一个元素添加到双端队列头部。 如果操作成功返回 true。
insertLast():将一个元素添加到双端队列尾部。如果操作成功返回 true。
deleteFront():从双端队列头部删除一个元素。 如果操作成功返回 true。
deleteLast():从双端队列尾部删除一个元素。如果操作成功返回 true。
getFront():从双端队列头部获得一个元素。如果双端队列为空,返回 -1。
getRear():获得双端队列的最后一个元素。 如果双端队列为空,返回 -1。
isEmpty():检查双端队列是否为空。
isFull():检查双端队列是否满了。

思路:数组

var MyCircularDeque = function (k) {
  this.data = [];
  this.length = k;
};

/**
 * Adds an item at the front of Deque. Return true if the operation is successful.
 * @param {number} value
 * @return {boolean}
 */
MyCircularDeque.prototype.insertFront = function (value) {
  if (this.data.length >= this.length) return false;
  this.data.unshift(value);
  return true;
};

/**
 * Adds an item at the rear of Deque. Return true if the operation is successful.
 * @param {number} value
 * @return {boolean}
 */
MyCircularDeque.prototype.insertLast = function (value) {
  if (this.data.length >= this.length) return false;
  this.data.push(value);
  return true;
};

/**
 * Deletes an item from the front of Deque. Return true if the operation is successful.
 * @return {boolean}
 */
MyCircularDeque.prototype.deleteFront = function () {
  if (this.isEmpty()) return false;
  this.data.shift();
  return true;
};

/**
 * Deletes an item from the rear of Deque. Return true if the operation is successful.
 * @return {boolean}
 */
MyCircularDeque.prototype.deleteLast = function () {
  if (this.isEmpty()) return false;
  this.data.pop();
  return true;
};

/**
 * Get the front item from the deque.
 * @return {number}
 */
MyCircularDeque.prototype.getFront = function () {
  if (this.isEmpty()) return -1;
  return this.data[0];
};

/**
 * Get the last item from the deque.
 * @return {number}
 */
MyCircularDeque.prototype.getRear = function () {
  if (this.isEmpty()) return -1;
  return this.data[this.data.length - 1];
};

/**
 * Checks whether the circular deque is empty or not.
 * @return {boolean}
 */
MyCircularDeque.prototype.isEmpty = function () {
  return !this.data.length;
};

3.最长数对链

题目:

给出 n 个数对。 在每一个数对中,第一个数字总是比第二个数字小。

现在,我们定义一种跟随关系,当且仅当 b < c 时,数对(c, d) 才可以跟在 (a, b) 后面。我们用这种形式来构造一个数对链。

给定一个数对集合,找出能够形成的最长数对链的长度。你不需要用到所有的数对,你可以以任何顺序选择其中的一些数对来构造。

思路:和最多数量的不重叠区间,还有最少箭戳破气球的题目一样,排序+栈,贪心比较

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

从后往前

/**
 * @param {number[][]} pairs
 * @return {number}
 */
var findLongestChain = function(pairs) {
  pairs.sort((a, b) => {
    if (a[0] !== b[0]) {
      return a[0] - b[0];
    }
    return a[1] - b[1];
  });
  let c = 0;
  let pre = Infinity;
  const l = pairs.length;
  for (let i = l - 1; i >= 0; i--) {
    const [start, end] = pairs[i];
    if (end < pre) {
      c++;
      pre = start;
    }
  }
  return c;
};

从前往后

/**
 * @param {number[][]} pairs
 * @return {number}
 */
var findLongestChain = function(pairs) {
  pairs.sort((a, b) => {
    if (a[1] !== b[1]) {
      return a[1] - b[1];
    }
    return a[0] - b[0];
  });
  let c = 0;
  let pre = -Infinity;
  for (const [start, end] of pairs) {
    if (start > pre) {
      c++;
      pre = end;
    }
  }
  return c;
};

4.回文子串

题目:

给定一个字符串,你的任务是计算这个字符串中有多少个回文子串。

具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被视作不同的子串。

思路:动态规划。对于字符串s[i][j],如果它是一个字符,那么是回文子串;如果是两个字符,那么比较s[i]和s[j];如果超过两个字符,那么就比较s[i]和s[j],且判断s[i+1][j-1]是否为回文子串,这样dp转移方程就出来了

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

/**
 * @param {string} s
 * @return {number}
 */
var countSubstrings = function(s) {
  let count = 0;
  const l = s.length;

  const dp = new Array(l).fill('').map(()=>new Array(l).fill(false))

  for (let j = 0; j < l; j++) { 
    for (let i = 0; i <= j; i++) {
      if (i == j) {   
        dp[i][j] = true;
        count++;
      } else if (j - i == 1 && s[i] == s[j]) {
        dp[i][j] = true;
        count++;
      } else if (j - i > 1 && s[i] == s[j] && dp[i + 1][j - 1]) {
        dp[i][j] = true;
        count++;
      }
    }
  }
  return count;
};

仔细观察,可以压缩成一维数组

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

/**
 * @param {string} s
 * @return {number}
 */
var countSubstrings = function(s) {
  let count = 0;
  const l = s.length;

  const dp = new Array(l).fill(false);

  for (let j = 0; j < l; j++) {
    for (let i = 0; i <= j; i++) {
      if (i == j) {
        dp[i] = true;
        count++;
      } else if (j - i == 1 && s[i] == s[j]) {
        dp[i] = true;
        count++;
      } else if (j - i > 1 && s[i] == s[j] && dp[i + 1]) {
        dp[i] = true;
        count++;
      }else{
          dp[i]=false
      }
    }
  }
  return count;
};

5.单词替换

题目:

在英语中,我们有一个叫做 词根(root)的概念,它可以跟着其他一些词组成另一个较长的单词——我们称这个词为 继承词(successor)。例如,词根an,跟随着单词 other(其他),可以形成新的单词 another(另一个)。

现在,给定一个由许多词根组成的词典和一个句子。你需要将句子中的所有继承词用词根替换掉。如果继承词有许多可以形成它的词根,则用最短的词根替换它。

你需要输出替换之后的句子。

思路:先将字典按照长度排序,然后将句子分割成单词,判断单词是否是以某个词根开头即可

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

/**
 * @param {string[]} dictionary
 * @param {string} sentence
 * @return {string}
 */
var replaceWords = function(dictionary, sentence) {
  dictionary.sort((a, b) => a.length - b.length);
  sentence = sentence.split(" ");
  return sentence.map((s) => {
    for (const d of dictionary) {
      if (s.startsWith(d)) {
        return d;
      }
    }
    return s;
  }).join(' ');
};

 

你可能感兴趣的:(求解方程,设计循环双端队列,最长数对链,回文子串,单词替换)