剑指offer面试题44 扑克牌的顺子(java实现)

算法思路:

1.对数组进行排序;

2.统计数组中0的个数;

3.统计排序之后的数组中相邻数组之间的空缺数进行判断。如果空缺的总数小于或者等于0的个数,那么这个数组是连续的;反之则不连续。

public class Solution {

	public boolean isContinuous(int[] numbers) {

		if (numbers == null || numbers.length != 5) {

			return false;

		}

		// 做三件事
		// 1.对数组进行排序
		// 2.统计数组中0的个数
		// 3.统计排序之后的数组中相邻数字之间的空缺总数

		// 1.对数组进行排序
		quickSortByPartition(numbers, numbers.length, 0, numbers.length - 1);

		// 2.统计数组中0的个数
		int numOf0 = 0;
		for (int i = 0; i < numbers.length; i++) {
			if (numbers[i] == 0) {
				numOf0++;
			}
		}

		// 统计排序数组中两两之间的间隔数
		// 定义一个指针,从数组的第一个非0元素开始

		int numOfGap = 0;
		// 指向前一个元素
		int small = numOf0;
		// 指向后一个元素
		int big = numOf0 + 1;
		// 在后一个元素不越界的情况下
		while (big < numbers.length) {

			if (numbers[small] == numbers[big]) {
				// 一旦相邻两元素相等,肯定不是顺子
				return false;
			}

			// 相邻两元素不等,现在肯定是big指向元素大于small指向元素
			if (numbers[big] - numbers[small] == 1) {
				// 此时两个元素正好相邻,两个指针后移
				small++;
				big++;
			} else {
				// 此时两个元素不相邻,中间隔的数>=1个
				// 获取当前这两个数字之间间隔几个数
				numOfGap = numbers[big] - numbers[small] - 1;
				// 判断拥有的0是否能补救
				if (numOfGap > numOf0) {
					// 所需间隔数>0的个数,无法补救,肯定不是顺子
					return false;
				} else {
					// 此时numOfGap <= numOf0,当前情况下可以补救,则进行补救,将0的个数减少
					// 即当前情况用去numOfGap个0
					numOf0 = numOf0 - numOfGap;
					small++;
					big++;
				}
			}

		}

		return true;

	}

	public void quickSortByPartition(int[] arr, int length, int start, int end) {
		if (start == end) {
			return;
		}
		
		int index = partition(arr, length, start, end);
		if (index > start) {
			quickSortByPartition(arr, length, start, index - 1); 
		}
		
		if (index < end) {
			quickSortByPartition(arr, length, index + 1, end);
		}
	}

	public int partition(int[] arr, int length, int start, int end) {

		if (arr == null || length <= 0 || start < 0 || end >= length) {
			System.out.println("数组输入有误");
			return -1;
		}

		// 随机选取一个支点
		int index = (start + end) / 2;
		// 交换支点和数组最后一个元素,此时支点元素变为数组中最后一个元素
		swap(arr,index, end);

		// small初始时指向开始元素的前一个位置,用于作为小于等于支点元素的边界索引
		int small = start - 1;

		for (index = start; index < end; index++) {

			// 如果index所指元素小于或者等于支点元素
			if (arr[index] < arr[end]) {
				small++;
				if (small != index) {
					swap(arr,index, small);
				}

			}

		}
		// 对small的索引加1,用于放置支点元素
		small++;
		// 交换small位置和end位置的元素,即将支点元素换到small位置
		swap(arr,small, end);

		return small;

	}

	/**
	 * 交换两个数
	 * @param arr 
	 */
	private void swap(int[] arr, int index1, int index2) {

		int temp = arr[index1];
		arr[index1] = arr[index2];
		arr[index2] = temp;

	}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值