1.链表中的下一个更大节点
题目:可以先将链表中的节点值放入一个数组,然后就是一个单调栈了。
从数组的尾部开始遍历,当栈顶元素小于等于当前节点值时,栈顶元素出栈,直到栈顶元素大于当前值或者栈为空。如果栈内没有值,则说明该元素对应的更大值是0;否则就是栈顶元素。
然后将当前元素入栈。
时间复杂度O(n),空间复杂度O(1)
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {number[]}
*/
var nextLargerNodes = function(head) {
const nums = [];
while (head) {
nums.push(head.val);
head = head.next;
}
const res = [0];
const stack = [nums.pop()];
while (nums.length) {
const item = nums.pop();
while (stack.length && item >= stack[0]) {
stack.shift();
}
if (!stack.length) {
res.unshift(0);
} else {
res.unshift(stack[0]);
}
stack.unshift(item);
}
return res;
};
2.飞地的数量
题目:
给出一个二维数组 A,每个单元格为 0(代表海)或 1(代表陆地)。
移动是指在陆地上从一个地方走到另一个地方(朝四个方向之一)或离开网格的边界。
返回网格中无法在任意次数的移动中离开网格边界的陆地单元格的数量。
思路:典型的dfs。从数组的四条边开始遍历,遇到陆地则深度优先地将相邻陆地置为0.最后重新遍历数组,找到剩余的陆地,这些陆地就不能离开网格,
时间复杂度O(mn),空间复杂度O(1)
/**
* @param {number[][]} grid
* @return {number}
*/
var numEnclaves = function(grid) {
const h = grid.length;
const w = grid[0].length;
const dfs = (i, j) => {
if (i < 0 || i >= h) return;
if (j < 0 || j >= w) return;
if (grid[i][j] === 0) return;
grid[i][j] = 0;
dfs(i, j + 1);
dfs(i, j - 1);
dfs(i + 1, j);
dfs(i - 1, j);
};
for (let i = 0; i < w; i++) {
dfs(0, i);
dfs(h - 1, i);
}
for (let i = 0; i < h; i++) {
dfs(i, 0);
dfs(i, w - 1);
}
let c = 0;
for (let i = 0; i < h; i++) {
for (let j = 0; j < w; j++) {
if (grid[i][j]) c++;
}
}
return c;
};
3.驼峰式匹配
题目:
如果我们可以将小写字母插入模式串 pattern 得到待查询项 query,那么待查询项与给定模式串匹配。(我们可以在任何位置插入每个字符,也可以插入 0 个字符。)
给定待查询列表 queries,和模式串 pattern,返回由布尔值组成的答案列表 answer。只有在待查项 queries[i] 与模式串 pattern 匹配时, answer[i] 才为 true,否则为 false。
思路:指针法。对于每个元素,从该元素起点left以及pattern起点right分别遍历,对于每一个right,都必须要找到对应的left使得item[left] = pattern[right]。对于item[left] !== pattern[right]时。有多种情况:
如果item[left]为大写字母,则该元素不符合条件。因为我们不能插入大写字母;
如果遍历left到末尾,仍不相同,则该元素不符合条件。因为pattern不能有多余的元素。
此时,left可以往右遍历,遇到相同的,则两个指针各+1,直到pattern遍历到末尾。
pattern遍历到末尾之后,还要判断item剩余的元素是否有大写字母
时间复杂度O(mn),空间复杂度O(1)
/**
* @param {string[]} queries
* @param {string} pattern
* @return {boolean[]}
*/
var camelMatch = function(queries, pattern) {
return queries.map((item) => {
let queryLeft = 0;
let patternLeft = 0;
const l1 = item.length;
const l2 = pattern.length;
while (queryLeft < l1 && patternLeft < l2) {
while (
item[queryLeft] !== pattern[patternLeft] &&
queryLeft < l1 &&
patternLeft < l2
) {
if (item[queryLeft].charCodeAt() < 90) return false;
queryLeft++;
}
if (item[queryLeft] !== pattern[patternLeft]) return false;
queryLeft++;
patternLeft++;
}
for (let i = queryLeft; i < l1; i++) {
if (item[i].charCodeAt() < 90) return false;
}
return true;
});
};
4.视频拼接
题目:
你将会获得一系列视频片段,这些片段来自于一项持续时长为 T 秒的体育赛事。这些片段可能有所重叠,也可能长度不一。
视频片段 clips[i] 都用区间进行表示:开始于 clips[i][0] 并于 clips[i][1] 结束。我们甚至可以对这些片段自由地再剪辑,例如片段 [0, 7] 可以剪切成 [0, 1] + [1, 3] + [3, 7] 三部分。
我们需要将这些片段进行再剪辑,并将剪辑后的内容拼接成覆盖整个运动过程的片段([0, T])。返回所需片段的最小数目,如果无法完成该任务,则返回 -1 。
思路:对于以i为起点的视频片段,可以记录对应的最大值right。然后,从时间0开始,每遍历一个时间,则更新一下当前的最大结束时间。如果最大时间 >= T,说明可以完成任务。
在遍历的时候,记录上次的max,如果当前时间等于上次的max,说明有新片段插入,此时视频片段数+1,再对结束时的max判断是否最后还需要一个视频。
时间复杂度O(n+ T),空间复杂度O(n)
/**
* @param {number[][]} clips
* @param {number} T
* @return {number}
*/
var videoStitching = function(clips, T) {
if(!T)return 0
const dp = new Array(T + 1).fill(0);
for (const [start, end] of clips) {
dp[start] = Math.max(dp[start], end);
}
if (dp[0] === 0) return -1;
let max = 0;
let pre = 0;
let c = 0;
for (let i = 0; i < T; i++) {
if (i > pre) return -1;
max = Math.max(dp[i], max);
if (i === pre) {
c++;
pre = max;
}
if (max >= T) break;
}
return c + (pre < T ? 1 : 0);
};
5.最长等差数列
题目:
给定一个整数数组 A
,返回 A
中最长等差子序列的长度。
回想一下,A
的子序列是列表 A[i_1], A[i_2], ..., A[i_k]
其中 0 <= i_1 < i_2 < ... < i_k <= A.length - 1
。并且如果 B[i+1] - B[i]
( 0 <= i < B.length - 1
) 的值都相同,那么序列 B
是等差的。
思路:和最长递增子序列类似,每一个下标记录对应的,以该元素为终点的,差值为n的等差数列长度,,然后每次往前找
时间复杂度O(n2),空间复杂度O(n2)
/**
* @param {number[]} A
* @return {number}
*/
var longestArithSeqLength = function(A) {
const l = A.length;
const dp = new Array(l).fill("").map(() => ({}));
let max = 0;
for (let i = 1; i < l; i++) {
for (let j = i - 1; j >= 0; j--) {
const dis = A[i] - A[j];
dp[i][dis] = Math.max(dp[i][dis] || 0, 1 + (dp[j][dis] || 0));
max = Math.max(max, dp[i][dis]);
}
}
return max + 1;
};