力扣刷题---数组篇

126 阅读3分钟

image.png

704. 二分查找 简单题

题意:
有序且无重复元素的数组中查找目标值target,找到返回其下标,没有找到返回-1 ==》可以考虑使用二分法
二分法时间复杂度: O(logn)
直接遍历数组查找时间复杂度: O(n)
其次,使用二分法时,注意区间开闭情况

image.png

var search = function(nums, target) {
    // right是数组最后一个数的下标,num[right]在查找范围内,是左闭右闭区间
    let mid, left = 0, right = nums.length - 1;
    // 当left=right时,由于nums[right]在查找范围内,所以要包括此情况
    while (left <= right) {
        // 位运算 + 防止大数溢出
        mid = left + ((right - left) >> 1);
        // 如果中间数大于目标值,要把中间数排除查找范围,所以右边界更新为mid-1;如果右边界更新为mid,那中间数还在下次查找范围内
        if (nums[mid] > target) {
            right = mid - 1;  // 去左面闭区间寻找
        } else if (nums[mid] < target) {
            left = mid + 1;   // 去右面闭区间寻找
        } else {
            return mid;
        }
    }
    return -1;
};

相关题目推荐

27. 移除元素 简单题

image.png 暴力解法

var removeElement = function(nums, val) {
   let len = nums.length;
   for(let i = 0; i < len; i++) {
       // 遇到待删除元素 ==》 原地删除该元素
       if(nums[i] === val) {
           let j = i+1;
           while(j < len) {
               nums[j-1] = nums[j];
               j++;
           }
           len--;
           i--; // i一定要减1(考虑出现删除连续的两个及以上的值时)
       }
   }
   return len;
};

双指针法

var removeElement = function(nums, val) {
    let slow = 0, fast = 0;
    while(fast < nums.length) {
        // 保留数值不等于val的元素
        if(nums[fast] !== val) {
            nums[slow] = nums[fast];
            slow++;
        }
        // 不论当前元素是否保留,fast都往后走
        fast++;
    }
    return slow;
};

相关题目推荐

  • 26.删除排序数组中的重复项
  • 283.移动零
  • 844.比较含退格的字符串
  • 977.有序数组的平方

977. 有序数组的平方 简单题

image.png

方法一: 暴力排序
时间复杂度: O(n+nlogn) ==> O(nlogn)
空间复杂度: O(1)

var sortedSquares = function(nums) {
    for(let i = 0; i < nums.length; i++) {
        nums[i] = nums[i] * nums[i];
    }
    nums.sort((a,b) => a-b);
    return nums;
};

方法二: 双指针法
时间复杂度: O(n)
空间复杂度: O(n)

image.png

var sortedSquares = function(nums) {
    let len = nums.length;
    let i = 0, j = len - 1, k = len - 1;
    // res新数组,k从下标len到0一个个存当前最大值
    let res = new Array(len).fill(0);
    // i,j 双指针, 从数组两端找平方值最大者
    while(i <= j) {
        let left = nums[i] * nums[i];
        let right = nums[j] * nums[j];
        if(left > right) {
            res[k--] = left;
            i++;
        }else {
            res[k--] = right;
            j--;
        }
    }
    return res;
};

209. 长度最小的子数组 中等题

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

image.png

image.png

方法一:暴力解法 居然可以过

var minSubArrayLen = function(target, nums) {
    let res = nums.length + 1;
    let sum = 0;
    for(let i = 0; i < nums.length; i++) {
        // 子序列起点为i
        sum = 0;
        for(let j = i; j < nums.length; j++) {
            sum += nums[j];
            if(sum >= target) {
                res = res < (j-i+1) ? res : (j-i+1);
                break; 
                // 因为是找符合条件最短的子序列,所以一旦符合条件就break
            }
        }
    }
    // 如果res没有被赋值,就返回0,说明没有符合条件的子序列
    return res === nums.length + 1? 0 : res;
};

方法二:滑动窗口

var minSubArrayLen = function(target, nums) {
    let i = 0, j = 0,len = nums.length;
    let sum = 0;
    let min = len + 1; // 子数组最大不会超过自身
    while(j < len) {
        sum += nums[j];
        // 窗口滑动
        while(sum >= target) {
            // 闭区间 [i, j]
            if(min > (j-i+1)) min = j-i+1;
            sum -= nums[i];
            i++;
        }
        j++;
    }
    return min == len + 1? 0: min;
};

相关题目推荐

59. 螺旋矩阵 II 中等题 这题要多写 !!!

image.png

方法一

var generateMatrix = function(n) {
    let res = Array.from(Array(n), () => Array(n).fill(0));
    let loop = Math.floor(n/2);
    let mid = Math.floor(n/2);
    let count = 1;
    let left = 0, right = n-1; // 记录当前圈的最左和最右
    // 外循环 控制圈数 内循环 控制四个方向
    while(loop--) {
        for(let col = left; col <= right; col++) {
            res[left][col] = count++; 
        }
        for(let row = left+1; row <= right; row++) {
            res[row][right] = count++;
        }
        for(let col = right-1; col>=left; col--) {
            res[right][col] = count++;
        }
        for(let row = right-1; row >= left+1; row--) {
            res[row][left] = count++;
        }
        left++;
        right--;
    }
    // 奇数,还需要填充res[mid][mid] 位置
    if(n%2 == 1) {
        res[mid][mid] = count;
    }
    return res;
};

方法二

var generateMatrix = function(n) {
    // let res = Array(n).fill(Array(n).fill(0)); 
    //==》 不能这样创建二维数组,会导致出错
    // 会导致创建的二维数组不同行之间的同一列指向同一片数据,一改全改
    let res = Array.from(Array(n),()=>Array(n).fill(0));//推荐这样创建二维数组
    let count = 1;
    let left = 0, top = 0;
    let bottom = n-1, right = n-1;
    while(left <= right) {
        // 行top不变,列从left到right
        for(let col = left; col <= right; col++){
            res[top][col] = count++;
        }
        // 列right不变,行从top+1到bottom
        for(let row = top+1; row <= bottom; row++) {
            res[row][right] = count++;
        }
        // 行bottom不变,列从right-1到left+1
        for(let col = right-1; col >= left; col--) {
            res[bottom][col] = count++;
        }
        // 列left不变,行从bottom-1到top+1
        for(let row = bottom-1; row>=top+1; row--){
            res[row][left] = count++;
        }
        left++;
        top++;
        right--;
        bottom--;
    }
    return res;
};

注意: 不要采用下列形式创建二维数组
错误写法: let res = Array(n).fill(Array(n).fill(0));

image.png

使用非for循环直接使用fill 创建二维数组,必须先给一维数组赋初始值,且为基本类型,再赋二维数组,如果直接给 fill 赋值为一个数组,会导致创建的二维数组不同行之间的同一列指向同一片数据,一改全改。 原因在 fill 官方文档里找到一句话:当一个对象被传递给 fill 方法的时候,填充数组的是这个对象的引用。

正确创建二维数组:
let res = Array.from(Array(n),()=>Array(n).fill(0));

相关题目推荐

  • 54.螺旋矩阵
  • 剑指Offer 29.顺时针打印矩阵