js(100)~[75] 颜色分类-单双指针

132 阅读1分钟

力扣本题传送门

我想的太简单了,最后console出来是真确答案,但就是执行不对,哎,想了也不能这么简单,我的简单错误代码如下 image.png

方法一

看了题解以后,发现用双指针,有循环一遍和循环2变得,就看明白了点儿,两次循环第一次把0放在前面第二次把1放在中间,代码如下

var sortColors = function (nums) {
	let n = nums.length;
	let index = 0;
	// 从前往后遍历,只要发现有0的数字就交换,同时索引位置增加
	for (let i = 0; i < n; i++) {
		if (nums[i] == 0) {
			// 这两句交换都ok
			// [nums[index], nums[i]] = [nums[i], nums[index]];
			[nums[i], nums[index]] = [nums[index], nums[i]];
			index++;
		}
	}
	console.log(nums, index)
	// 经过上一轮之后索引位置前的数字都是0了,下一轮遍历就把后面所有1的数字都交换到中间
	for (let i = index; i < n; i++) {
		if (nums[i] == 1) {
			[nums[i], nums[index]] = [nums[index], nums[i]];
			index++;
		}
	}
};

题外话,双指针还是咩有掌握啊,我最开始想这个题目的时候,也是双指针,是一个往前一个往后,但是实现的跟我想象的比一样,我是想着0往前,2往后,1不变位置.我在集在方法一的基础上改造实现的错误代码如下

var sortColors = function (nums) {
	let n = nums.length;
	let index = 0;
	// 从前往后遍历,只要发现有0的数字就交换,同时索引位置增加
	for (let i = 0; i < n; i++) {
		if (nums[i] == 0) {
			// 这两句交换都ok
			// [nums[index], nums[i]] = [nums[i], nums[index]];
			[nums[i], nums[index]] = [nums[index], nums[i]];
			index++;
		}
	}
	console.log(nums)
	// 经过上一轮之后索引位置前的数字都是0了,下一轮遍历就把后面所有1的数字都交换到中间
	index = nums.length - 1;
	for (let i = index; i > 0; i--) {
		if (nums[i] == 2) {
			[nums[i], nums[index]] = [nums[index], nums[i]];
			index--;
		}
	}
};

其他人双指针实现正确的.

方法二

var sortColors = function (nums) {
  let n = nums.length;
  // p0确保前面位置的元素都是0
  let p0 = 0,
    // p2确保后面位置的元素都是2
    p2 = n - 1;
  // 为什么退出的时候是<=p2,因为p2指针后面的元素都是2了,但并不是p2指向的这个位置也是2,所以是<=
  /* 举例来说 [2,0,1] ,经过一次交换变成了[1,0,2],这时p2指向0元素,如果就此就退出循环,那就还是无序的*/
  for (let i = 0; i <= p2; i++) {
    // 把前面的2全部都交换到后面去
    while (i <= p2 && nums[i] == 2) {
      [nums[i], nums[p2]] = [nums[p2], nums[i]];
      p2--;
    }
    // p0记住前面有多少个0,并确保p0前面的元素都是0
    if (nums[i] == 0) {
      [nums[i], nums[p0]] = [nums[p0], nums[i]];
      p0++;
    }
  }
};