【数组】荷兰国旗问题

4 篇文章 0 订阅

1.先看一个简单的例子

题干如下:

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

解法一:

public static int[] changeArrByNum(int[] arr, int num) {
    int left = 0;
    for (int i = 0; i < arr.length; i++) {
      if (arr[i] <= num) {
        //发现小于等于num的数:和left边界交换
        int temp = arr[left];
        arr[left] = arr[i];
        arr[i] = temp;
        left++;//left往左的都是<=num的
      }
    }
    return arr;
}

解法二:原理是双指针实现,类似快排划分

public static int[] changeArrByNum2(int[] arr, int num) {
    int L = 0;
    int R = arr.length - 1;
    while (L < R) {
      while (arr[R] > num && L < R) {//右边找一个数,<=num
        R--;
      }
      while (arr[L] <= num && L < R) {//左边找一个数,>num
        L++;
      }
      int temp = arr[L];
      arr[L] = arr[R];
      arr[R] = temp;
    }
    return arr;
}

2.荷兰国旗问题

荷兰国旗问题:定一个数组arr, 和一个数num, 请把小于等于num的数放在数组的左边,等于num的放中间,大于num的数放在数组的右边。要求:额外空间复杂度O(1),时间复杂度O(n)。

public static void swap(int[] arr, int i, int j) {
    int temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}
  
public static int[] partition(int[] arr, int left, int right, int num) {
    int L = left - 1;
    int R = right + 1;
    int cur = left;
    while (cur < R) {
      if (arr[cur] < num) {
        swap(arr, cur++, ++L);//①
      } else if (arr[cur] > num) {
        swap(arr, cur, --R);//②
      } else {
        cur++;//③等于num。直接比较下一个数
      }
    }
    return arr;
}

注意:

  • 在上述的维护过程中:数组arr[]下标L以及L以左的数据被维护成小于num,下标R以及R以左的数据被维护成大于num,中间的数据是等于num的。
  • ①处swap(arr, cur++, ++L);,为什么cur++:因为左边已经已经遍历过了,对arr[cur]来说,要么是自己和自己交换,要么是等于num的数和自己交换(主要是因为左边已经遍历过了,情况是已知的)。
  • ②处swap(arr, cur, --R);,为什么cur没有自加:因为右边交换过来的数字arr[r-1]没有遍历过,不知道>、<还是=,需要进一步判断。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值