03. 数组中重复的数字
题目介绍
找出数组中重复的数字。
在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
示例
输入:
[2, 3, 1, 0, 2, 2, 5, 3]
输出:[ [ 2, 3 ], [ 3, 2 ] ]
限制:2 <= n <= 100000
答案
时间空间复杂度:O(n), O(n)
/**
* @param {number[]} nums
* @return {number}
*/
var findRepeatNumber = function(nums) {
const numSet = {}
nums.forEach(num => {
if(numSet[num]) numSet[num] += 1;
else numSet[num] = 1;
})
const res = []
Object.entries(numSet).forEach(arr => {
const [key, value] = arr;
if(value >= 2) res.push([Number(key), value])
})
return res;
};
04. 二维数组中的查找
题目介绍
在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
示例
现有矩阵 matrix 如下:
[
[1, 4, 7, 11, 15],
[2, 5, 8, 12, 19],
[3, 6, 9, 16, 22],
[10, 13, 14, 17, 24],
[18, 21, 23, 26, 30]
]
给定 target = 5,返回 true。
给定 target = 20,返回 false。
限制:
0 <= n <= 1000
0 <= m <= 1000
答案
时间空间复杂度:O(nlogn), O(1)
/**
* @param {number[][]} matrix
* @param {number} target
* @return {boolean}
*/
var findNumberIn2DArray = function (matrix, target) {
return matrix.some(array => {
return search(array, target) !== -1
})
};
const search = function (nums, target) {
let left = 0,
right = nums.length - 1,
mid;
while (left <= right) {
mid = Math.floor((left + right) / 2);
if (nums[mid] < target) {
left = mid + 1;
} else if (nums[mid] > target) {
right = mid - 1;
} else {
return mid;
}
}
return -1;
}
05. 替换空格
题目介绍
请实现一个函数,把字符串 s 中的每个空格替换成"%20"。
示例
输入:s = "We are happy."
输出:"We%20are%20happy."
0 <= s 的长度 <= 10000
答案
时间空间复杂度:O(n), O(1)
/**
* @param {string} s
* @return {string}
*/
var replaceSpace = function (s) {
return s.replace(/ /g, '%20');
};
09. 用两个栈实现队列
题目介绍
用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )
示例
输入:
["CQueue","appendTail","deleteHead","deleteHead"]
[[],[3],[],[]]
输出:[null,null,3,-1]
输入:
["CQueue","deleteHead","appendTail","appendTail","deleteHead","deleteHead"]
[[],[],[5],[2],[],[]]
输出:[null,-1,null,null,5,2]
1 <= values <= 10000
最多会对 appendTail、deleteHead 进行 10000 次调用
答案
时间空间复杂度:插入和删除O(1), O(n)
const addStack = new Stack();
const deleteStack = new Stack();
function CQueue(commands = [], values = []) {
const res = [];
commands.forEach((item, index) => {
if (['CQueue', 'appendTail'].includes(item)) {
res.push(null)
values[index].forEach(value => {
addStack.push(value);
});
}
if (['deleteHead'].includes(item)) {
if (deleteStack.size() === 0) {
while (addStack.size() > 0) {
deleteStack.push(addStack.pop());
}
}
res.push(deleteStack.pop() || -1)
}
});
return res;
}
10-I. 斐波那契数列
题目介绍
写一个函数,输入 n ,求斐波那契(Fibonacci)数列的第 n 项。斐波那契数列的定义如下:
F(0) = 0, F(1) = 1
F(N) = F(N - 1) + F(N - 2), 其中 N > 1.
斐波那契数列由 0 和 1 开始,之后的斐波那契数就是由之前的两数相加而得出。
答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。
示例
输入:n = 2
输出:1
输入:n = 5
输出:5
答案
时间空间复杂度:插入和删除O(n), O(1)
/**
* @param {number} n
* @return {number}
*/
var fib = function (n) {
if ([0, 1].includes(n)) return n;
let prev = 0;
let prevLast = 1;
let temp = null;
for (let i = 2; i <= n; i++) {
temp = prevLast;
prevLast = (prevLast + prev) % 1000000007;
prev = temp;
}
return prevLast;
};
06. 从尾到头打印链表
题目介绍
输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。
示例
输入:head = [1,3,2]
输出:[2,3,1]
答案
时间空间复杂度:O(1), O(n)
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {number[]}
*/
var reversePrint = function (head) {
const result = [];
while(head!==null) {
result.unshift(head.val);
head = head.next
}
return result
};
13. 机器人的运动范围
题目介绍
地上有一个m行n列的方格,从坐标 [0,0] 到坐标 [m-1,n-1] 。一个机器人从坐标 [0, 0] 的格子开始移动,它每次可以向左、右、上、下移动一格(不能移动到方格外),也不能进入行坐标和列坐标的数位之和大于k的格子。例如,当k为18时,机器人能够进入方格 [35, 37] ,因为3+5+3+7=18。但它不能进入方格 [35, 38],因为3+5+3+8=19。请问该机器人能够到达多少个格子?
示例
输入:m = 2, n = 3, k = 1
输出:3
输入:m = 3, n = 1, k = 0
输出:1
1 <= n,m <= 100
0 <= k <= 20
答案
时间空间复杂度:O(mn), O(mn)
/**
* @param {number} m
* @param {number} n
* @param {number} k
* @return {number}
*/
var movingCount = function (m, n, k) {
const arr = []
for (let i = 0; i < m; i++) {
arr[i] = []
for (let j = 0; j < n; j++) {
arr[i][j] = '-';
}
}
return dfs(arr, m, n, k, 0, 0)
}
var dfs = function (arr, m, n, k, i, j) {
if (i < 0 || i > m - 1 || j < 0 || j > n - 1 || arr[i][j] !== '-') return 0;
const addValue = (String(i) + String(j)).split('').reduce((total, val) => {
return Number(total) + Number(val);
})
if (addValue > k) return 0;
const x = [1, 0, -1, 0];
const y = [0, 1, 0, -1];
let res = 1;
arr[i][j] = '*'
for (let idx = 0; idx < 4; idx++) {
res = res + dfs(arr, m, n, k, i + x[idx], j + y[idx])
}
return res;
}
18. 删除链表的节点
题目介绍
给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。
返回删除后的链表的头节点。
示例
输入: head = [4,5,1,9], val = 5
输出: [4,1,9]
解释: 给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9.
答案
时间空间复杂度:O(n), O(1)
核心:head是一条链,pre和node都是上面的指针
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @param {number} val
* @return {ListNode}
*/
var deleteNode = function (head, val) {
let pre = head;
let node = pre.next;
if(pre.val === val) {
return head.next;
}
while(node) {
if(pre.val === val) {
pre.next = node.next;
break;
}
pre = node;
node = node.next;
}
return head;
};
47. 礼物的最大价值
题目介绍
在一个 m*n 的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于 0)。你可以从棋盘的左上角开始拿格子里的礼物,并每次向右或者向下移动一格、直到到达棋盘的右下角。给定一个棋盘及其上面的礼物的价值,请计算你最多能拿到多少价值的礼物?
示例
输入:
[
[1,3,1],
[1,5,1],
[4,2,1]
]
输出: 12
解释: 路径 1→3→5→2→1 可以拿到最多价值的礼物
0 < grid.length <= 200
0 < grid[0].length <= 200
答案
时间空间复杂度:O(n), O(mn)
/**
* @param {number[][]} grid
* @return {number}
*/
var maxValue = function (grid) {
const m = grid.length;
const n = grid[0].length;
const dp = [];
for (let i = 0; i < m; i++) {
dp[i] = []
for (let j = 0; j < n; j++) {
dp[i][j] = 0;
}
}
dp[0][0] = grid[0][0];
// 初始化第一行和第一列值
for (let i = 1; i < m; i++) {
dp[i][0] = grid[i][0] + dp[i - 1][0];
}
for (let j = 1; j < n; j++) {
dp[0][j] = grid[0][j] + dp[0][j - 1];
}
// 从grid[1][1]开始循环
for (let i = 1; i < m; i++) {
for (let j = 1; j < n; j++) {
dp[i][j] = grid[i][j] + Math.max(dp[i - 1][j], dp[i][j - 1]);
}
}
return dp[m - 1][n - 1];
};
16. 数值的整数次方
题目介绍
实现函数double Power(double base, int exponent),求base的exponent次方。不得使用库函数,同时不需要考虑大数问题。
示例
输入: 2.00000, 10
输出: 1024.00000
输入: 2.10000, 3
输出: 9.26100
输入: 2.00000, -2
输出: 0.25000
解释: 2-2 = 1/22 = 1/4 = 0.25
-100.0 < x < 100.0
n 是 32 位有符号整数,其数值范围是 [−231, 231 − 1]
答案
时间空间复杂度:O(n), O(mn)
思路
递归,成倍进行乘积。
/**
* @param {number} x
* @param {number} n
* @return {number}
*/
var myPow = function (x, n) {
if (n === 0) return 1;
let res = x;
for (let i = 2; i <= Math.abs(n); i = i * 2) {
res *= res;
if (i * 2 > Math.abs(n) && i !== Math.abs(n)) {
res *= myPow(x, Math.abs(n) - i);
}
}
if (n < 0) {
res = 1 / res
}
return res
};