1.寻找数组的中心索引
给你一个整数数组 nums ,请计算数组的 中心下标 。
数组 中心下标 是数组的一个下标,其左侧所有元素相加的和等于右侧所有元素相加的和。
如果中心下标位于数组最左端,那么左侧数之和视为 0 ,因为在下标的左侧不存在元素。这一点对于中心下标位于数组最右端同样适用。
如果数组有多个中心下标,应该返回 最靠近左边 的那一个。如果数组不存在中心下标,返回 -1 。
示例 1:
输入:nums = [1, 7, 3, 6, 5, 6]
输出:3
解释:
中心下标是 3 。
左侧数之和 sum = nums[0] + nums[1] + nums[2] = 1 + 7 + 3 = 11 ,
右侧数之和 sum = nums[4] + nums[5] = 5 + 6 = 11 ,二者相等。
示例 2:
输入:nums = [1, 2, 3]
输出:-1
解释:
数组中不存在满足此条件的中心下标。
算法代码解析:
/**
* @param {number[]} nums
* @return {number}
**/
var pivotIndex = function(nums) {
//算出一个数组的所有元素之和
const total = nums.reduce((a,b) => a+b,0);
let sum = 0;
for(let i = 0; i < nums.length; i++){
//计算左右2侧当前和
//左侧sum
//右侧total - sum - nums[i]
//也就是total - sum - nums[i] = sum
//最终等式 2*sum + nums[i] === total
if( 2*sum + nums[i] === total){
return i
}
sum += nums[i]
}
//上面等式不成立 说明不存在这个下标
return -1
};
2.搜索插入位置
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 O(log n) 的算法。
示例 1:
输入: nums = [1,3,5,6], target = 5
输出: 2
示例 2:
输入: nums = [1,3,5,6], target = 2
输出: 1
算法代码解析:
/**
* @param {number[]} nums
* @param {number} target
* @return {number}
*/
var searchInsert = function(nums, target) {
let index = 0
for(let i = 0;i < nums.length; i ++){
//找到目标
if(target === nums[i]){
return i
}else{
//没找到就定一下位置
if(target < nums[0]){
index = 0
}else if(target > nums[nums.length-1]){
index = nums.length
}else if(target > nums[i]){
index = i+1
}
}
}
//没找到位置最终定位置
return index
};
3.合并区间
以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。
示例 1:
输入:intervals = [[1,3],[2,6],[8,10],[15,18]]
输出:[[1,6],[8,10],[15,18]]
解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].
示例 2:
输入:intervals = [[1,4],[4,5]]
输出:[[1,5]]
解释:区间 [1,4] 和 [4,5] 可被视为重叠区间。
算法代码解析:
/**
* @param {number[][]} intervals
* @return {number[][]}
*/
function merge(intervals){
//先按照每个二维数组第一个元素排序
intervals.sort((a,b)=> a[0] - b[0]);
//合并计算
const resArr = [];
for(let i = 1; i < intervals.length; i++){
//对于[1,3]和[2,6] 比较3和2 如果 3 >= 2 则合并
// Math.max 比较[1,3]和[2,6] 数组第二个元素 3和6谁比较大 大的取值当做右边边界
if (intervals[i][0] <= intervals[i - 1][1]){
intervals[i] = [intervals[i - 1][0], Math.max(intervals[i - 1][1], intervals[i][1])]
}
else{
// 不能合并则将上一个合并结果加入
resArr.push(intervals[i - 1])
}
}
// 最后一次的结果需要额外放入
resArr.push(intervals[intervals.length - 1])
//将结果返回
return resArr;
}
4.旋转矩阵
给你一幅由 N × N 矩阵表示的图像,其中每个像素的大小为 4 字节。请你设计一种算法,将图像旋转 90 度。
示例 1:
给定 matrix =
[
[1,2,3],
[4,5,6],
[7,8,9]
],
原地旋转输入矩阵,使其变为:
[
[7,4,1],
[8,5,2],
[9,6,3]
]
示例 2:
给定 matrix =
[
[ 5, 1, 9,11],
[ 2, 4, 8,10],
[13, 3, 6, 7],
[15,14,12,16]
],
原地旋转输入矩阵,使其变为:
[
[15,13, 2, 5],
[14, 3, 4, 1],
[12, 6, 8, 9],
[16, 7,10,11]
]
算法代码解析:
/**
* @param {number[][]} matrix
* @return {void} Do not return anything, modify matrix in-place instead.
*/
var rotate = function (matrix) {
//倒数
matrix = matrix.reverse();
const res = [];
for (let i = 0; i < matrix.length; i++) {
//每个for外层都生成一个数组
let firstArr = [];
for (let j = 0; j < matrix[i].length; j++) {
//我们需要要的是这样结果
// matrix[0][0]
// matrix[1][0]
// matrix[2][0]
firstArr.push(matrix[j][i]);
}
res.push(firstArr);
}
for (let k = 0; k < res.length; k++) {
matrix[k] = res[k]
}
};
5.零矩阵
编写一种算法,若M × N矩阵中某个元素为0,则将其所在的行与列清零
示例 1:
输入:
[
[1,1,1],
[1,0,1],
[1,1,1]
]
输出:
[
[1,0,1],
[0,0,0],
[1,0,1]
]
示例 2:
输入:
[
[0,1,2,0],
[3,4,5,2],
[1,3,1,5]
]
输出:
[
[0,0,0,0],
[0,4,5,0],
[0,3,1,0]
]
算法代码解析:
/**
* @param {number[][]} matrix
* @return {void} Do not return anything, modify matrix in-place instead.
*/
var setZeroes = function (matrix) {
const resultArr = [];
const arrIndex = [];
//检测一行数组中是否存在为0的 并标记一下下标位置
for (let i = 0; i < matrix.length; i++) {
let index = matrix[i].indexOf(0);
arrIndex.push([]);
while (index !== -1) {
//标记0位置 存放到数组arrIndex
arrIndex[i].push(index);
//继续查找下一个
index = matrix[i].indexOf(0, index + 1);
}
}
//复制一份matrix
resultArr.push(...matrix);
//进行标记0的位置进行处理
for (let j = 0; j < arrIndex.length; j++) {
let target = null;
let curIndex = 0;
//如果当前存在target标记的0出现 则每个标记进行一次行和列清空操作
while (arrIndex[j].length > 0 && curIndex < arrIndex[j].length) {
//设置当前行为0
if (curIndex === 0) resultArr[j] = resultArr[j].map(() => 0);
//每个行都有几个0出现位置
target = arrIndex[j][curIndex];
curIndex++;
//设置当前列为0
resultArr.map((item, index) => {
item[target] = 0;
matrix[index] = item;
});
}
}
};
6.最长公共前缀
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 “”。
示例 1:
输入:strs = [“flower”,“flow”,“flight”]
输出:“fl”
示例 2:
输入:strs = [“dog”,“racecar”,“car”]
输出:“”
解释:输入不存在公共前缀。
算法解析:
/**
* @param {string[]} strs
* @return {string}
*/
var longestCommonPrefix = function(strs) {
//极端情况处理strs = ['']
if((strs.length === 0) || (!strs[0])) return ''
//极端情况处理strs = ['a']
if(strs.length === 1 && strs[0].length === 1) return strs[0].slice(0,1);
let start = strs[0].slice(0,1)
let startNum = 0;
for(let i = 1;i < strs.length; i++){
//如果存在至少一个公共前缀标记一下个数
if(start === strs[i].slice(0,1)) startNum++;
//存在一个字符都不相同 那么这个肯定没有公共前缀
else return '';
}
//如果存在至少一个公共前缀 那么计算总共有几个公共前缀
if(startNum === strs.length-1){
let switchs = true;
let endIndex = 0
let startWith = null
while(switchs){
//从前2个前缀向右依次比对看有几个相同前缀
endIndex++;
startWith = strs[0].slice(0,endIndex);
let targetNum = 0
strs.map((item,indx) =>{
//如果存在一个没有公共前缀就停止继续比对
if(startWith !== item.slice(0,endIndex)){
switchs = false
startWith = strs[0].slice(0,endIndex-1)
}
if(startWith === item) targetNum = indx;
})
//极端情况strs = ["flower","flower","flower","flower"] startWith === item都成立
if(startWith === strs[0] && targetNum === strs.length-1){
switchs = false;
startWith = strs[0]
}
}
//返回公共前缀
return startWith
}
};