高频数组算法

本文介绍了四种数组处理算法:使用二分查找在有序数组中搜索目标值,原地移除数组中指定值的元素,对有序数组进行平方操作并保持排序,以及找到和大于等于目标值的最小子数组长度。分别给出了暴力遍历和优化的双指针等解法。
摘要由CSDN通过智能技术生成

1.二分查找

给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。

示例 1:

输入: nums = [-1,0,3,5,9,12], target = 9     
输出: 4       
解释: 9 出现在 nums 中并且下标为 4     

使用普通的遍历

var search = function(nums, target) {
for(var i=0;i<nums.length;i++){
    if(nums[i]==target){
        return i
    }
}
return -1

};

使用二分查找

// 二分查找
    var serach = function (nums, target) {
      let left = 0;
      let right = nums.length;
      let mid = Math.ceil((left + right) / 2);
      console.log(mid);
      while (left < right) {
        if (nums[mid] > target) {
          right = mid - 1;
        } else if (nums[mid] < target) {
          left = mid + 1;
        } else {
          return mid;
        }
      }
      return -1;
    };
    serach(nums, target);
    console.log(serach(nums, target));

2.移除元素

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。

不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

示例 1: 给定 nums = [3,2,2,3], val = 3, 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。 你不需要考虑数组中超出新长度后面的元素。

方法一:使用新的数组来存储

  var nums = [2, 3, 4, 2];
    var val = 2;
    // 移除元素
    var dele = function (nums, val) {
      let arr = [];
      for (let i = 0; i < nums.length; i++) {
        if (nums[i] !== val) {
          arr.push(nums[i]);
        }
      }
      return arr.length;
    };
    console.log(dele(nums, val));

方法二:双重循环

 // 方法二:双重遍历
    var dele = function (nums, val) {
      for (let i = 0; i < nums.length; i++) {
        if (nums[i] == val) {
          //发现需要移除的元素,就将数组集体向前移动一位
          //num[0]=2
          for (let j = i + 1; j < nums.length; j++) {
            nums[j - 1] = nums[j]; //nums[0]=3,nums[1]=4,nums[2]=2
          }
          i--; // 因为下标i以后的数值都向前移动了一位,所以i也向前移动一位
          nums.length--; // 此时数组的大小-1
        }
      }
      return nums.length;
    };
    console.log(dele(nums, val));

 3.有序数组的平方

给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。

示例 1: 输入:nums = [-4,-1,0,3,10] 输出:[0,1,9,16,100] 解释:平方后,数组变为 [16,1,0,9,100],排序后,数组变为 [0,1,9,16,100]

暴力排序

最直观的想法,莫过于:每个数平方之后,排个序

 var nums = [2, 3, 4];
    var sortarr = function (nums) {
      let arr = [];
      for (let i = 0; i < nums.length; i++) {
        arr.push(nums[i] * nums[i]);
      }
      arr.sort((a, b) => {
        return a - b;
      });
      return arr;
    };
    console.log(sortarr(nums));

双指针法

数组其实是有序的, 只不过负数平方之后可能成为最大数了。

那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。

 var sortarr = function (nums) {
      let n = nums.length;
 //创建一个数组并填充对应的数 [0, 0, 0, 0, 0, 0, 0, 0]
      let temp = new Array(n).fill(0);
      let left = 0;
      let right = n - 1;
      let k = n - 1;
      while (left <= right) {
        if (nums[left] * nums[left] > nums[right] * nums[right]) {
          temp[k] = nums[left] * nums[left];
          k--;
          left++;
        } else {
          temp[k] = nums[right] * nums[right];

          k--;
          right--;
        }
      }
      return temp;
    };
    console.log(sortarr(nums));

4.长度最小的子数组

给定一个含有 n 个正整数的数组和一个正整数 target 。

 找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] 并返回其长度。如果不存在符合条件的子数组,返回 0 。

方法一:暴力解法

时间复杂度: O (n2) 空间复杂度 :O(1)
思路:用i 和 j 表示子数组的头序号和尾序号,
           用rl表示最小连续子数组长度,初始值为原数组长度
          sum储存子数组内数组和
          sumlength子数组长度

 var nums = [2, 3, 1, 2, 4, 3];
    var target = 7;
    var minarr = function (nums, target) {
      let r = 0;
      let l = 0;
      let sumlength = nums.length;
      let sum;
      let rl = 0;
      for (let i = 0; i < nums.length; i++) {
        sum = 0; //初始化,开始踢掉头一个数,重新找最小子数组
        for (let j = i; j < nums.length; j++) {
          sum += sum[j];
          rl = j - i + 1;
          if (sum >= target) {
            sumlength = sumlength > rl ? rl : sumlength;
          }
        }
      }
      return sumlength > rl ? 0 : sumlength;
    };

方法二:双指针法

 var minarr = function (nums, target) {
      let r = 0;
      let l = 0;
      let sumlength = nums.length;
      let sum = 0;
      let rl = 0;
      // 遍历整个数组
      while (r < nums.length) {
        sum += nums[r++]; //小于目标值,移动指针,累加sum

        while (sum >= target) {
          rl = r - l; // r-l就是队列中元素的长度
          sumlength = sumlength > rl ? rl : sumlength;
          sum -= nums[l++]; // 用l指针控制弹出队头的元素
        }
      }
      return sumlength > rl ? 0 : sumlength;
    };

    console.log(minarr(nums, target));

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值