JS实现 LeetCode 数组类算法(四)

更多算法实现见:https://github.com/Erindcl/Daily-algorithm

532. 数组中的K-diff数对

  • 给定一个整数数组和一个整数 k, 你需要在数组里找到不同的 k-diff 数对。这里将 k-diff 数对定义为一个整数对 (i, j), 其中 i  j 都是数组中的数字,且两数之差的绝对值是 k.、
  • 注意:
  • 数对 (i, j) 和数对 (j, i) 被算作同一数对。
  • 数组的长度不超过10,000。
  • 所有输入的整数的范围在 [-1e7, 1e7]。

分析:将数组升序排序后,遍历数组,在遍历的过程中需排除k-diff对(i,j)中i重复以及k-diff对(i,j)中j重复的情况,之后再判断(i,j)中 i 与 j 的差值是否等于 k。代码如下:

var findPairs = function(nums, k) {
    let count = 0, len = nums.length;
    nums.sort((a,b) => {return a - b;});  // 升序排序
    for(let i = 0; i < len; i++){
        let curr = nums[i] + k;
        if (i -1 >= 0 && nums[i] == nums[i - 1]) {  // 排除k-diff对(i,j)中i重复的情况
            continue;
        }
        for (let j = i + 1; j < len; j++) {
            if (nums[j + 1] == nums[j] && j + 1 < len) {  // 排除k-diff对(i,j)中j重复的情况
                continue;
            }
            if (nums[j] == curr) {
                count++;
            }
        }
    }
    return count;
};

其他实现:

var findPairs = function(nums, k) {
  nums.sort((x, y) => x - y)
  let foo = new Set()
  let res = 0
  for (let i = 0; i < nums.length; i++) {
    let j = i + 1

    while (nums[j] - nums[i] <= k && j < nums.length) {
      if (nums[j] - nums[i] === k && !foo.has(nums[i])) {
        res++
        foo.add(nums[i])
      }
      j++
    }
  }

  return res
};

561. 数组拆分 I

  • 给定长度为 2n 的数组, 你的任务是将这些数分成 n 对, 例如 (a1, b1), (a2, b2), ..., (an, bn) ,使得从1 到 n 的 min(ai, bi) 总和最大。
  • 提示:
  • n 是正整数,范围在 [1, 10000].
  • 数组中的元素范围在 [-10000, 10000].

代码如下:

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

566. 重塑矩阵

  • 在MATLAB中,有一个非常有用的函数 reshape,它可以将一个矩阵重塑为另一个大小不同的新矩阵,但保留其原始数据。
  • 给出一个由二维数组表示的矩阵,以及两个正整数rc,分别表示想要的重构的矩阵的行数和列数。
  • 重构后的矩阵需要将原始矩阵的所有元素以相同的行遍历顺序填充。
  • 如果具有给定参数的reshape操作是可行且合理的,则输出新的重塑矩阵;否则,输出原始矩阵。

分析:首先判断原矩阵与重塑后的矩阵元素个数是否相同,如果不相同则返回原矩阵。如果相同则进行一下操作,将原矩阵的所有元素全部依次存进一个数组,遍历数组将数组元素按照重塑矩阵的行列要求放入一个新的二维数组中,最后这个二维数组即为重塑后的矩阵。代码如下:

var matrixReshape = function(nums, r, c) {
    let pR = nums.length, pC = nums[0].length;
    if (pR * pC != r * c) {
        return nums;
    }
    let newArr = [], resultArr = [], count = 0;
    for (var value of nums) {
      newArr.push(...value);
    }
    for (let i = 0; i < r; i++) {
        let currArr = [];
        for (let j = 0; j < c; j++) {
            currArr.push(newArr[count]);
            count ++;
        }
        resultArr.push(currArr);
    }
    return resultArr;
};

其他实现:

var matrixReshape = function(nums, r, c) {
  if (nums.length * nums[0].length !== r * c) return nums
  let res = []
  let arr = []
  for (let i = 0; i < nums.length; i++) {
    arr.push(...nums[i])
  }
  for (let j = 0; j < r; j++) {
    res.push(arr.splice(0, c))
  }
  return res
};

581. 最短无序连续子数组

  • 给定一个整数数组,你需要寻找一个连续的子数组,如果对这个子数组进行升序排序,那么整个数组都会变为升序排序。
  • 你找到的子数组应是最短的,请输出它的长度。

分析:将排序后的数组与排序前的数组进行比较,分别从前和从后遍历两数组并进行比较,在遍历过程中两数组出现差异的地方记录下来,两头出现差异的索引相减就可计算处中间调换了顺序的元素有多少个。代码如下:

var findUnsortedSubarray = function(nums) {
    let leftIndex = 0, len = nums.length, rightIndex = len - 1;
    let beforArr = [...nums]; 
    nums.sort((a,b) => {return a -b;});
    for (let i = 0; i < len; i++) {
        leftIndex = i;
        if (beforArr[i] != nums[i]) {
            break;
        }
    }
  
    for (let i = len - 1; i >= 0; i--) {
        rightIndex = i;
        if (beforArr[i] != nums[i]) {
            break;
        }
    }
    if (rightIndex <= leftIndex) {
      return 0;
    }
    return rightIndex - leftIndex + 1;
};

其他实现:

var findUnsortedSubarray = function(nums) {
    let length = nums.length,
        beg = -1,
        end = -2,
        min = nums[length - 1],
        max = nums[0]
    
    for (let i = 0; i < length; i++) {
        max = Math.max(max, nums[i])
        min = Math.min(min, nums[length - 1 - i])
        
        if(nums[i] < max) end = i
        if(nums[length - 1 - i] > min) beg = length - 1 - i
    }
    
    return end - beg + 1
};

605. 种花问题

  • 假设你有一个很长的花坛,一部分地块种植了花,另一部分却没有。可是,花卉不能种植在相邻的地块上,它们会争夺水源,两者都会死去。
  • 给定一个花坛(表示为一个数组包含0和1,其中0表示没种植花,1表示种植了花),和一个数 。能否在不打破种植规则的情况下种入 朵花?能则返回True,不能则返回False。

分析:根据计算相邻两个1之间有几个数确定空位能种值花卉的最大数,再将所有空位种植花卉最大数相加即可得到整个花园还可种植花卉的最大数,即可确定最大能放多少。特别注意首尾的空位,要想在首尾能种植花卉就假设,数组索引-2和length+1的位置值为1。代码如下:

var canPlaceFlowers = function(flowerbed, n) {
    let sum = 0; // 花园中能存放花的最大数量
    let index = - 2; // 当前1所在的数组中的索引 初始值设为-2的原因是 当数组第一个元素为0能置1时其前后位都得不为1,故-1位置不能设为1的起始位 要设置-2为1的起始位才行
    for(let i = 0; i < flowerbed.length; i++) {
        if (flowerbed[i] == 1) {
            let curr1 = parseInt((i - index) / 2) - 1; // parseInt() 丢弃小数部分取整数部分
            sum += curr1 < 0 ? 0 : curr1;
            index = i;
        }
    }
    let curr2 = parseInt((flowerbed.length + 1 - index) / 2) - 1;  // 当数组末尾还有一大部分的连续0出现时 需要将末尾能放置1的位置数一同加上 注意此处flowerbed.length + 1的原因与index初始值设为-2原因类似
    sum += curr2 < 0 ? 0 : curr2;
    return sum >= n ? true : false;
};

其他实现:

var canPlaceFlowers = function(flowerbed, n) {
    let temp = 1;
	let ans = 0;

	for (var i = 0; i < flowerbed.length; i++) {
		if (flowerbed[i] === 0) {
			temp++;
		} else if (flowerbed[i] === 1 && temp > 0) {
			ans += Math.floor((temp - 1) / 2);
			temp = 0;
		}
	}

    ans += Math.floor(temp / 2);

	return ans >= n;
};

猜你喜欢

转载自blog.csdn.net/m0_37747665/article/details/81115665