1.删除数组重复项

image.png
目的:升序数组去重,不创建新数组,原地删除
思路:

  1. 双指针遍历数组,left从0不动,right从0开始遍历
  2. 如果left === right,则right继续遍历,否则left后移一位,将right指向的值赋给left,right继续遍历
  3. 保证数组的前left均不相同,且按顺序排列,即前left项去重

    1. function (nums) {
    2. let left = 0;
    3. let right = 0;
    4. if (!Array.isArray(nums)) return;
    5. for (let i = right; right < nums.length; right++) {
    6. if (nums[left] !== nums[right]) {
    7. nums[++left] = nums[right];
    8. }
    9. }
    10. return nums.slice(0, left + 1);
    11. };
    12. let nums = [0, 0, 1, 1, 1, 2, 2, 3, 3, 4];
    13. console.log(removeDuplicates(nums)); // [0, 1, 2, 3, 4]

2.买卖股票的最佳时机 II

image.png
目的:给一个数组,按照买卖股票思路,计算最大的收益值
思路:其实就是计算后一项减前一项的差值,max就是差为正值的和

  1. var maxProfit = function(prices) {
  2. let max = 0
  3. if (prices.length === 0) {
  4. return 0
  5. }
  6. for (let i=0; i<prices.length; i++) {
  7. if ((prices[i+1] - prices[i]) > 0) {
  8. max += (prices[i+1] - prices[i])
  9. }
  10. }
  11. return max
  12. }

3.旋转数组

image.png
目的:将数组的每一项都向后移动k位,如果大于length,则从第一位开始
思路:

  1. 创建一个newArr与原数组一致
  2. 遍历newArr,将i向前移动放回原数组
  3. 关键在于向前移动后的index值为:(i + k) % length

    1. function (nums, k) {
    2. let res = [];
    3. for (let i = 0; i < nums.length; i++) {
    4. res[i] = nums[i];
    5. }
    6. // 放回原数组,并且 i 超前移动 k 位
    7. for (let i = 0; i < res.length; i++) {
    8. nums[(i + k) % res.length] = res[i];
    9. }
    10. };

    4.存在重复数组(判断是否有重复)

    1. var containsDuplicate = function (nums) {
    2. let map = new Map();
    3. if (!Array.isArray(nums)) return;
    4. return nums.some((item) => {
    5. if (map.has(item)) {
    6. return true;
    7. } else {
    8. map.set(item, true);
    9. }
    10. });
    11. };

    image.png

5.只出现一次的数字
image.png

目的:查找数组中只出现一次的值
思路:

  1. 设置一个Map对象,记录数组的item,以及出现的次数
  2. 遍历map对象,找到value为1的key

    1. var singleNumber = function (nums) {
    2. let map = new Map();
    3. let res = null;
    4. if (Array.isArray(nums)) {
    5. nums.forEach((item) => {
    6. // 如果map存在该项
    7. if (map.has(item)) {
    8. let count = map.get(item);
    9. map.set(item, ++count);
    10. } else {
    11. map.set(item, 1);
    12. }
    13. });
    14. map.forEach((value, key) => {
    15. if (value === 1) {
    16. res = key;
    17. }
    18. });
    19. }
    20. return res;
    21. };

    6.两个数组的交集

    image.png
    目的:求两个数组的交集,并且保证出现的数量一致
    思路:

  3. 用一个hashMap记录num1的item,以及出现的次数

  4. 遍历num2,如果map上存在就把count—,并且push该item到res
    var intersect = function (nums1, nums2) {
    let map = new Map();
    let res = []
    nums1.forEach((item) => {
     if (map.has(item)) {
       let count = map.get(item);
       map.set(item, ++count);
     } else {
       map.set(item, 1);
     }
    });
    nums2.forEach(item => {
     if (map.has(item)) {
       let count = map.get(item)
       count > 0 && res.push(item)
       map.set(item, --count)
     }
    })
    return res
    };
    

7.加一

image.png
方法一:通过join方式转化为字符串,再通过BigInt转化为数字,最后转化为number数组
注意:

  1. 使用BigInt是因为,Number只能转化2^53以内的数字
  2. BigInt类型只能和BigInt类型相加
    var plusOne = function (digits) {
    let res = [];
    if (!Array.isArray(digits)) return;
    let num = BigInt(digits.join("")) + BigInt(1);
    String(num)
     .split("")
     .forEach((item) => res.push(Number(item)));
    return res;
    };
    

方法二:从后往前遍历,从最末位开始+1,如果有一位小于10则return,如果直到遍历接受都没有小于10,说明是999, 9999,这种数字,则数组头部补上一个1

function (digits) {
  for (let i = digits.length - 1; i >= 0; i--) {
    if (digits[i] + 1 < 10) {
      digits[i] = digits[i] + 1;
      return digits;
    } else {
      digits[i] = 0;
    }
  }
  digits.unshift(1)
  return digits
};

8.移动0

image.png
目的:将数组中所有的0往后移动,不创建新数组,原地移动
思路:双指针法

  1. 创建right 指针遍历数组,找到非0的item
  2. 创建left指针,从第一位开始,如果right位不为0,则与right位交换位置
  3. 因为left和right同时从0开始,所以如果两项都不为0,交换相当于不变,并且left和right均+1
  4. 如果突然right为0了,说明此时left也为0了,那么left不会向前进,先等right继续前进
  5. 等到right不为0的时候,交换left和right的值,left+1
    var moveZeroes = function (nums) {
    let left = 0
    for (let right = 0; right < nums.length; right++) {
     if (nums[right] !== 0) {
       let temp = nums[left]
       nums[left] = nums[right]
       nums[right] = temp
       left++
     }
    }
    return nums
    };
    

9.两数之和

image.png
方法1:

  1. 通过hashMap方式,遍历nums,记录item以及 item 的index值
  2. 再次遍历nums,查找map中是否hash target-num
    function (nums, target) {
    let map = new Map();
    nums.forEach((item, index) => map.set(item, index));
    for (let i = 0; i < nums.length; i++) {
     if (map.has(target - nums[i])) {
       let j = map.get(target - nums[i]);
       if (j !== i) {
         return [i, j];
       }
     }
    }
    };
    
    方法2:每次遍历时,截取后部分数组,查找是否indexOf > -1
    关键在于:nums.slice(i+1)是后部分数组
    function (nums, target) {
    for (let i = 0; i < nums.length; i++) {
     let t = target - nums[i];
     let j = nums.slice(i + 1).indexOf(t);
     if (j > -1) {
       return [i, j + i + 1];
     }
    }
    };
    

10.有效的数独

image.png
思路:

  1. for for 遍历二维数组,获取到对应的行 i, 列 j, num
  2. 通过 row 记录 i 行的值,判断是否存在重复
  3. 通过 col 记录 j 列的值,判断是否存在重复
  4. 将数组分为

1, 2, 3
4, 5, 6
7, 8, 9
九个区域,作为 boxIndex,设置box记录每个box的key,判断是否存在重复

function (board) {
  // 记录是否存在相同的值
  let row = {};
  let col = {};
  let box = {};
  // 遍历行
  for (let i = 0; i < board.length; i++) {
    // 遍历列
    for (let j = 0; j < board[i].length; j++) {
      let num = board[i][j];
      // num = . 时不记录到 col
      if (num === ".") {
        continue;
      }
      // 计算 boxIndex,将数独分为
      // 1, 2, 3
      // 4, 5, 6
      // 7, 8, 9
      // 九个模块,每个模块添加 boxIndex + num 为唯一 key
      let boxIndex = Math.floor(i / 3) * 3 + Math.floor(j / 3); // 每三行,模块会多3
      // 判断 同一row, col, box 中是否存在相同的值
      if (row[i + "" + num] || col[j + "" + num] || box[boxIndex + "" + num]) {
        return false;
      }
      // row 添加 行号+num 作为 key
      row[i + "" + num] = true;
      // col 添加 列号+num 作为 key
      col[j + "" + num] = true;

      box[boxIndex + "" + num] = true;
    }
  }
  return true;
};

11.旋转数组(未解决,矩阵)

去完成