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(' ');
};