荷兰旗问题 指定数分小于、等于、大于区间

172 阅读2分钟

题目

给定一个数组arr,和一个数num,请把小于等于num的数放在数组的左边,大于num的 数放在数组的右边。要求额外空间复杂度O(1),时间复杂度O(N)

  • 最值得关注的是空间复杂度O(1),意味着不能开辟新的数组空间
  • 设定一个小于区间,区间指针从-1开始,当arr[i]<=num 时,将arr[i]和小于区间的下一个位置数互换,然后区间指针+1,将arr[i]囊括进去;当arr[i]>num时,跳过即可
  • 价值是如何在空间复杂度为O(1)的情况,进行分左右区间
let arr = [3, 5, 6, 7, 4, 3, 5, 8];

function cutting(arr, num) {
  let left = -1;

  for (let i = 0; i < arr.length; i++) {
    if (arr[i] > num) {
      continue;
    } else {
      [arr[left + 1], arr[i]] = [arr[i], arr[left + 1]];
      left++;
    }
  }
}

cutting(arr, 5);
console.log(arr); //[3, 5, 4, 3, 5, 7, 6, 8],7前面的都比5小,7后面的都比5大

荷兰国旗问题

给定一个数组arr,和一个数num,请把小于num的数放在数组的左边,等于num的数放在数组的中间,大于num的数放在数组的右边。要求额外空间复杂度O(1),时间复杂度O(N)

  • 设定一个小于区间,区间指针从-1开始,当arr[i]<num 时,将arr[i]和小于区间的下一个位置数互换,然后区间指针+1,将arr[i]囊括进去;
  • 如果arr[i]==num ,跳过
  • 设定一个大于区间,区间指针从数组长度的位置开始,当arr[i]>num 时,将arr[i]和大于区间的左边下一个位置互换,然后大于区间指针位置--,将arr[i]囊括进去;当互换后,i位置不++,而是再根据上面的情况判断一次,因为换过来的新数并不知道具体大小
  • 当遍历的i==大于区间的指针时,退出循环
let arr = [3, 5, 6, 3, 4, 5, 2, 6, 9, 0];

function cutting(arr, num) {
  let left = -1;
  let right = arr.length;

  for (let i = 0; i <= right; i++) {
    if (i == right) {
      break;
    }
    if (arr[i] < num) {
      [arr[left + 1], arr[i]] = [arr[i], arr[left + 1]];
      left++;
    } else if (arr[i] == num) {
      continue;
    } else {
      [arr[i], arr[right - 1]] = [arr[right - 1], arr[i]];
      right--;
      //使得下轮比较从右边交换过来的数
      i--;
    }
  }
}
cutting(arr, 5);
console.log(arr); //[ 3, 0, 3, 4, 2, 5, 5, 9, 6, 6 ]