数组和字符串基本算法

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
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

追逐梦想之路_随笔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值