牛客网算法基础班笔记-Chapter2

荷兰国旗问题

问题描述:

给定一个整数数组,给定一个整数值num,这个值在原数组中一定存在,要求把数组中小于num的元素放到数组的左边,大于num的元素放到数组的右边,等于num的元素放到数组的中间,最终返回一个整数数组,其中只有两个值,分别是等于num的数组部分的左右两个下标值。

例如,给定数组:[8, 1, 4, 5, 3, 9, 5, 10, 5],给定一个num值5,那么经过处理原数组可能得一种情况是:[1 4 3 5 5 5 10 9 8 ],需要注意的是,小于5的部分不需要有序,大于5的部分也不需要有序,返回等于5部分的左右两个下标,即[3, 5]

思路:

对数组进行分区,主要分三种情况。

首先明确的是,最终数组从左到右会被划分为:小于num的区间,等于num的区间,大于num的区间

初始时小于num的区间为数组以左,即(-∞,-1),大于num区间为(a.length,+∞)。

1. 当前遍历元素小于num时, 将小于num区间的下一个位置的元素和当前遍历元素交换,然后小于num区间向右扩大一个位置,并且遍历指针也右移一位。

2.当前遍历元素大于num时, 将大于num区间的前一个位置的元素和当前遍历元素交换,然后大于num区间向左扩大一个位置,遍历指针不动!!!因为之前交换来当前遍历位置的元素未被遍历过,并不知道该元素是大于还是小于还是等于num,需要对该元素继续判断,因此遍历指针不动,进入下一次循环,对该元素再进行判断。

3.当前遍历元素等于num时,遍历指针直接向后移动一位。

代码:

public class NetherlandFlag {
	public static int[] partition(int[] a, int left, int right, int num) {
		/*
		 * less为小于num区域的右边界,即最终结果left到less为小于num的元素区间
		 * 初始值设为left-1,遍历中右移
		 */
		int less = left - 1;
		/*
		 *more为大于num区域的右边界,即最终结果more到right为大于num的元素区间
		 *初始值设为right+1,遍历中左移
		 */
		int more = right + 1;
		int cur = left;
		
		while(cur < more) {
			/*
			 * 当cur指向的元素小于num时 
			 * 将less所指位置的下一个位置(++less)的元素和cur指向元素交换 
			 * 然后cur指针前进
			 */
			if(a[cur] < num) {
				/*
				 * less++; 
				 * swap(a, less, cur); 
				 * cur++;
				 */
				swap(a, ++less, cur++);
			}
			/*
			 * 当cur指向的元素大于num时 
			 * 将more所指位置的前一个位置(--more)的元素和cur指向元素交换 
			 * 然后cur指针不动!!!!
			 * 此时换过来的元素有可能小于num或等于num或大于num 需要继续进入下次循环
			 */
			//注意!!!这里要写else if,才是三种情况挑一种执行
			else if(a[cur] > num) {
				swap(a, --more, cur);
			}
			//当cur指向元素等于num时,cur指针直接向后移动
			else {
				cur++;
			}
		}
		//结果返回一个包含两个元素的数组,表示等于num的元素区间为[less+1, more-1]
		return new int[] {less + 1, more - 1};
	}
	
	private static void swap(int[]
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值