题解 | #扑克牌顺子,最优解时间复杂度O(n),空间复杂度O(1)#

扑克牌顺子

http://www.nowcoder.com/practice/762836f4d43d43ca9deb273b3de8e1f4

最优解时间复杂度O(n),空间复杂度O(1)

关键点:

如何在O(n)的时间复杂度,O(1)的空间复杂度内判断数组是否有重复元素?

对于已知最大值和最小值的数组,我们将array[i]的元素放到array[i] - 1的位置上,但是本题中数组大小只能是5,所以咱们array[i]放的位置就是array[i] % 5,比如,3,8,13都在数组下标为3的这个位置上,5,10都在0这个位置上。只要array[array[i] % 5] % 5 == array[i] % 5 && i != array[i] % 5,就代表同一个位置,出现了相同的元素

举例如下

当i == 0会发生3轮交换

1,2,6,4,3

第一轮交换 array[i] == 1

2,1,6,4,3

第二轮交换 array[i] == 2

6,1,2,4,3

第三轮交换 array[i] == 6 满足 array[6 % 5] % 5 == 6 % 5 && i != 6 % 5

虽然1和6实际不相等,但是对于扑克牌顺子这个题来说,只要max-min大于4其实也就不是顺子了,所以这个地方可以直接返回false

具体代码如下

if (numbers == null || numbers.length < 5) {
            return false;
        }
        int min = 13;
        int max = 0;
        int spNumber = 5;
        for (int i = 0; i < numbers.length; ++i) {
            // 将每个数字放到自己的位置上
            int num = numbers[i];
            if (num == 0) {
                continue;
            }
            if (num < min) {
                min = num;
            }
            if (num > max) {
                max = num;
            }
            if (numbers[num % spNumber] == num % spNumber && (num % spNumber) != i && numbers[num % spNumber] != 0) {
                // 发现了重复的元素
                return false;
            }
            while (i != numbers[i] % spNumber) {
                int temp = numbers[numbers[i] % spNumber];
                if (numbers[i] == 0) {
                    break;
                }
                if (temp % spNumber == numbers[i] % spNumber && temp != 0 && numbers[i] != 0) {
                    // 交换过程中发现了重复元素
                    return false;
                }
                numbers[numbers[i] % spNumber] = numbers[i];
                numbers[i] = temp;
            }
        }
        if (max - min <= 4) {
            return true;
        }
        return false;
全部评论

相关推荐

头像
04-26 15:00
已编辑
算法工程师
点赞 评论 收藏
转发
点赞 收藏 评论
分享
牛客网
牛客企业服务