1.山羊拉丁文
题目:
给定一个由空格分割单词的句子 S。每个单词只包含大写或小写字母。
我们要将句子转换为 “Goat Latin”(一种类似于 猪拉丁文 - Pig Latin 的虚构语言)。
山羊拉丁文的规则如下:
如果单词以元音开头(a, e, i, o, u),在单词后添加"ma"。
例如,单词"apple"变为"applema"。
如果单词以辅音字母开头(即非元音字母),移除第一个字符并将它放到末尾,之后再添加"ma"。
例如,单词"goat"变为"oatgma"。
根据单词在句子中的索引,在单词最后添加与索引相同数量的字母'a',索引从1开始。
例如,在第一个单词后添加"a",在第二个单词后添加"aa",以此类推。
返回将 S 转换为山羊拉丁文后的句子。
思路:遍历就行,先将句子分割成数组,然后拼接
时间复杂度O(n),空间复杂度O(n)
/**
* @param {string} S
* @return {string}
*/
var toGoatLatin = function(S) {
const s = ["a", "e", "i", "o", "u"];
const words = S.split(" ");
const temp = "a";
words.forEach((item, index) => {
if (s.includes(item[0].toLowerCase())) {
words[index] = `${item}ma${temp.repeat(index + 1)}`;
} else {
words[index] = `${item.slice(1)}${item[0]}ma${temp.repeat(index + 1)}`;
}
});
return words.join(" ");
};
2.较大分组的位置
题目:
在一个由小写字母构成的字符串 S 中,包含由一些连续的相同字符所构成的分组。
例如,在字符串 S = "abbxxxxzyy" 中,就含有 "a", "bb", "xxxx", "z" 和 "yy" 这样的一些分组。
我们称所有包含大于或等于三个连续字符的分组为较大分组。找到每一个较大分组的起始和终止位置。
最终结果按照字典顺序输出。
思路:用双指针法,记录重复字符串的开始和结束下标,下标差大于等于2就符合条件
时间复杂度O(n),空间复杂度O(n)
/**
* @param {string} S
* @return {number[][]}
*/
var largeGroupPositions = function(S) {
let s = S[0];
let start = 0,
end = 0;
const l = S.length;
const res = [];
if (l < 3) return res;
for (let i = 0; i < l; ) {
while (S[i] === s) {
end = i;
i++
}
if (end - start >= 2) {
res.push([start, end]);
}
start = end = i;
s=S[i]
i++
}
if (end - start >= 2) {
res.push([start, end]);
}
return res;
};
3.翻转图像
题目:
给定一个二进制矩阵 A,我们想先水平翻转图像,然后反转图像并返回结果。
水平翻转图片就是将图片的每一行都进行翻转,即逆序。例如,水平翻转 [1, 1, 0] 的结果是 [0, 1, 1]。
反转图片的意思是图片中的 0 全部被 1 替换, 1 全部被 0 替换。例如,反转 [0, 1, 1] 的结果是 [1, 0, 0]。
思路:可以在水平翻转的同时将0和1反转,借助位运算异或^,将1和0反转
时间复杂度O(n²),空间复杂度O(1),原地算法,不需要额外的空间
/**
* @param {number[][]} A
* @return {number[][]}
*/
var flipAndInvertImage = function(A) {
const h = A.length;
if (!h) return A;
const w = A[0].length;
for (let i = 0; i < h; i++) {
for (let j = 0; j < w / 2; j++) {
[A[i][j], A[i][w - j - 1]] = [A[i][w - j - 1] ^ 1, A[i][j] ^ 1];
}
}
return A;
};
4.矩形重叠
题目:
矩形以列表 [x1, y1, x2, y2]
的形式表示,其中 (x1, y1)
为左下角的坐标,(x2, y2)
是右上角的坐标。
如果相交的面积为正,则称两矩形重叠。需要明确的是,只在角或边接触的两个矩形不构成重叠。
给出两个矩形,判断它们是否重叠并返回结果。
思路:两个矩形判断是否重叠,有两种办法,第一个方法,固定一个矩形,判断另一个矩形的四个点是否在第一个矩形内,只要有一个点在第一矩形内,就重叠。第二个方法就是判断两个矩形中心点的距离,两个中心点x/y轴的距离都小于对应方向长度和的一半就行
这里用第二种方法
/**
* @param {number[]} rec1
* @param {number[]} rec2
* @return {boolean}
*/
const inRange = (value, min, max) => {
return value > min && value < max;
};
var isRectangleOverlap = function (rec1, rec2) {
const ax = (rec1[0] + rec1[2]) / 2;
const ay = (rec1[1] + rec1[3]) / 2;
const bx = (rec2[0] + rec2[2]) / 2;
const by = (rec2[1] + rec2[3]) / 2;
const h1 = rec1[3] - rec1[1];
const h2 = rec2[3] - rec2[1];
const w1 = rec1[2] - rec1[0];
const w2 = rec2[2] - rec2[0];
return (
inRange(Math.abs(bx - ax), -1, (w1 + w2) / 2) &&
inRange(Math.abs(by - ay), -1, (h1 + h2) / 2)
);
};
5.矩阵中的幻方
题目:
3 x 3 的幻方是一个填充有从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。
给定一个由整数组成的 grid
,其中有多少个 3 × 3 的 “幻方” 子矩阵?(每个子矩阵都是连续的)。
思路:遍历所有的3×3矩阵,记录第一行的和,然后就是计算每一行和每一列的差,可以在同一轮遍历同时计算出行和列的和,调换x/y的值就行。
时间复杂度,是O(3n),也就是O(n),空间复杂度O(1)
/**
* @param {number[][]} grid
* @return {number}
*/
var numMagicSquaresInside = function(grid) {
const h = grid.length;
let count = 0;
if (!h) return count;
const w = grid[0].length;
if (h < 3 || w < 3) return count;
for (let i = 0; i < h - 2; i++) {
for (let j = 0; j < w - 2; j++) {
if (checkGrid(i, j)) count++;
}
}
function checkGrid(i, j) {
const set = new Set();
let rowSum;
for (let row = 0; row < 3; row++) {
let sum = 0;
let cSum = 0;
for (let col = 0; col < 3; col++) {
if(grid[i + row][j + col]>9||grid[i + row][j + col]<1)return false
if (set.has(grid[i + row][j + col])) return false;
set.add(grid[i + row][j + col]);
sum += grid[i + row][j + col];
cSum += grid[i + col][j + row];
}
rowSum = rowSum || sum;
if (sum !== rowSum) return false;
if (rowSum !== cSum) return false;
}
if (grid[i][j] + grid[i + 2][j + 2] !== grid[i][j + 2] + grid[i + 2][j])
return false;
return true;
}
return count;
};