《剑指Offer》-61-扑克牌中的顺子

发布时间 2023-08-08 22:11:18作者: YaosGHC

判断是否为连续的数字,需要额外考虑的情况有一个,就是 0 可以代表任何数字,并且最多出现两次

给出的长度为 5 的数组不一定是顺序

	bool isStraight(vector<int>& nums) {
		sort(nums.begin(), nums.end());
		// 没有 0 的情况

		if (nums[0] == 0) {
			// 只有一个 0 的情况
			if (nums[1] == 0) {

			}
			else {
				// 有两个 0 的情况,必定是从 0 开始?不一定
			}
		}
		else {
			// 没有 0 的情况
		}
	}

分类讨论的想法很快就被否决了,我想到了《剑指Offer》前面的数组题目中涉及到的,利用数组下标,因为很明显,数组下标也是一个连续的数列,可以用于建立一个映射关系

判断连续,一个一个确认,但是很明显由于 0 的特殊存在和规则,从小往大数并不合理,那么就从大往小数,最大的数字一定是确定的!

那么数的过程中出现了对不上的数字怎么办呢?用 0 补,如果有的话,那我怎么知道有没有呢?用一个指针从最左边开始向右移动,排序后的 0 (如果存在)一定在最左边!

那么这道题目的解题思路就出来了,双指针:

head1 头指针初始位置指向最左(最小的)数,head2 尾指针指向最右(最大的)数

head2 从右向左移动,检查下一个数字是否比上一个数字小 1,如果不是,确认差了几个数字,然后去检查左指针指向是否为 0,是 0 就可以补一个向右移动一位表示用掉了(这里差如果大于 2 可以直接 false)

能够补上就继续走,走到两个指针相遇则为 true

不是 0,补不上则为 false

	bool isStraight(vector<int>& nums) {
		sort(nums.begin(), nums.end());
		int point1 = 0, point2 = 3, diff;
		while (point2 != point1) {
			diff = nums[point2] - nums[point2 + 1];
			if (diff > 3) return false;
			while (diff > 1) {
				if (nums[point1] == 0) {
					point1++;
					diff--;
				}
				else return false;
			}
			point2--;
		}
		return true;
	}

死在[0,0,2,2,5]

  1. 没有考虑到元素重复的情况
  2. 差值相减写反了
  3. 最外层while循环退出条件也不对
  4. 若干副牌,不止两张王,那么最极端的情况就是 5 个 0

第一份 AC 代码

	bool isStraight(vector<int>& nums) {
		sort(nums.begin(), nums.end());
		int point1 = 0, point2 = 3, diff;
		if (nums[point2] == 0) return true;
		while (point2 >= point1) {
			if (nums[point2]==0) break;
			diff = nums[point2+1] - nums[point2];
			if (diff > 4 || diff == 0) return false;
			while (diff > 1) {
				if (nums[point1] == 0) {
					point1++;
					diff--;
				}
				else return false;
			}
			point2--;
		}
		return true;
	}

但是这样内存占用率太高

	bool isStraight(vector<int>& nums) {
		sort(nums.begin(), nums.end());
		int point1 = 0, point2 = 3, diff;
		while (point2 >= point1 && nums[point2] != 0) {
			diff = nums[point2+1] - nums[point2];
			if (diff > 4 || diff == 0) return false;
			while (diff > 1) {
				if (nums[point1] == 0) {
					point1++;
					diff--;
				}
				else return false;
			}
			point2--;
		}
		return true;
	}

而且其实也没有用上下标,可能将过程和排序过程结合会更好