数字序列分组算法

题目:

需要把数组里的数(每个数的取值都是1-9)分成多个小组,分小组的规则是:3个相同的数或者3个连续的数,当所有的数都可以被分组,则为完全分组。

设计一个算法,判断数组是否能完全分组。

例如[1, 1, 2, 2, 2, 3, 3, 3, 4],可分为 123   123   234(完全分组),

注意:若先把222  333分为一组,则会导致出现bug,判断为不可完全分组。


以下提供2个方法,均为c++实现:

方法一: 先查找相同数,并标记出来,再将还没标记的数按连续数方式查找;若得出不可完全分组,再将该数组先按连续数查找再按相同数查找(原理同上),得出可不可完全分组。

bool CanGroup(vector<int>& nums) {
	int n = nums.size(), i = 0, j = 1, k = 2, sign = true;
	// 若数组长度不是3的倍数,则无法分组
	if (n % 3 != 0)		return false;
	sort(nums.begin(), nums.end());
	vector<int> newNums(nums);
	// 查找相同3个数,并标记为已分组(使用-1表示已分组)
	while (i < n) {
		if (nums[i] == nums[i + 1] && nums[i + 1] == nums[i + 2]) {
			newNums[i] = newNums[i + 1] = newNums[i + 2] = -1;
			i = i + 3;
		} else {
			i++;
		}
	}
	i = 0;
	// 查找连续3个数,并标记为已分组(使用-1表示已分组)
	while (k < n) {
		while (newNums[i] == -1 && i < j) {
			i++;
		}
		while (newNums[j] == -1 && j < k) {
			j++;
		}
		while (newNums[k] == -1 && k < n) {
			k++;
		}
		if (nums[i] + 1 == nums[j] && nums[j] + 1 == nums[k]) {
			newNums[i] = newNums[j] = newNums[k] = -1;
		} else if (nums[i] + 2 != nums[k]) {
			k++;
		} else if (nums[i] + 1 != nums[j]) {
			j++;
		}
	}
	for (int i = 0; i < n; i++) {
		if (newNums[i] != -1)	sign = false;
	}
	if (!sign) {
		i = 0, j = 1, k = 2;
		for (int i = 0; i < newNums.size(); i++) {
			newNums[i] = 1;
		}
		// 查找连续3个数,并标记为已分组(使用-1表示已分组)
		while (k < n) {
			while (newNums[i] == -1 && i < j) {
				i++;
			}
			while (newNums[j] == -1 && j < k) {
				j++;
			}
			while (newNums[k] == -1 && k < n) {
				k++;
			}
			if (nums[i] + 1 == nums[j] && nums[j] + 1 == nums[k]) {
				newNums[i] = newNums[j] = newNums[k] = -1;
			} else {
				if (nums[i] + 2 != nums[k]) {
					k++;
				}
				if (nums[i] + 1 != nums[j]) {
					j++;
				}
			}
		}
		i = 0;
		// 查找相同3个数,并标记为已分组(使用-1表示已分组)
		while (i < n) {
			while (newNums[i] == -1 || newNums[i + 1] == -1 || newNums[i + 2] == -1) {
				i++;
			}
			if (nums[i] == nums[i + 1] && nums[i + 1] == nums[i + 2]) {
				newNums[i] = newNums[i + 1] = newNums[i + 2] = -1;
				i = i + 3;
			} else {
				i++;
			}
		}
		for (int i = 0; i < n; i++) {
			if (newNums[i] != -1)	return false;
		}
	}
	return true;
}

方法二(优化算法):

循环查找相同数和连续数,查到一种,最慢指针 i 才可以右移,循环查找结束之后,判断有无完全分组。

bool CanGroupOptimize(vector<int>& nums) {
	int n = nums.size(), i = 0, j = 1, k = 2, Stop = false;
	// 若数组长度不是3的倍数,则无法分组
	if (n % 3 != 0)		return false;
	sort(nums.begin(), nums.end());//数据排序
	vector<int> newNums(nums);//初始化标志数组
	while (!Stop) {
		Stop = true;
		// 循环查找相同3个数,并标记为已分组(使用-1表示已分组)
		while (nums[i] == nums[i + 1] && nums[i + 1] == nums[i + 2]) {
			newNums[i] = newNums[i + 1] = newNums[i + 2] = -1;
			Stop = false;
			i = i + 3;
			j = i + 1;
			k = j + 1;
			if (i >= n) {
				return true;
			}
		}
		// 循环查找连续3个数,并标记为已分组(使用-1表示已分组)
		while (k < n) {
			while (newNums[i] == -1 && i < j) {
				i++;
			}
			while (newNums[j] == -1 && j < k) {
				j++;
			}
			while (newNums[k] == -1 && k < n) {
				k++;
			}
			if (nums[i] + 1 == nums[j] && nums[j] + 1 == nums[k]) {
				newNums[i] = newNums[j] = newNums[k] = -1;
				Stop = false;
			} else {
				while (nums[i] + 2 != nums[k] && k < n) {
					k++;
				}
				while (nums[i] + 1 != nums[j] && j < k) {
					j++;
				}
			}
		}
	}
	//检索分组标志数组
	for (int i = 0; i < n; i++) {
		if (newNums[i] != -1)	return false;
	}
	return true;
}

运行结果:

 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_xian_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值