leetcode
leetcode 2151 ~ 2200
数组中最长的方波

数组中最长的方波

难度:

标签:

题目描述

You are given an integer array nums. A subsequence of nums is called a square streak if:

  • The length of the subsequence is at least 2, and
  • after sorting the subsequence, each element (except the first element) is the square of the previous number.

Return the length of the longest square streak in nums, or return -1 if there is no square streak.

A subsequence is an array that can be derived from another array by deleting some or no elements without changing the order of the remaining elements.

 

Example 1:

Input: nums = [4,3,6,16,8,2]
Output: 3
Explanation: Choose the subsequence [4,16,2]. After sorting it, it becomes [2,4,16].
- 4 = 2 * 2.
- 16 = 4 * 4.
Therefore, [4,16,2] is a square streak.
It can be shown that every subsequence of length 4 is not a square streak.

Example 2:

Input: nums = [2,3,5,6,7]
Output: -1
Explanation: There is no square streak in nums so return -1.

 

Constraints:

  • 2 <= nums.length <= 105
  • 2 <= nums[i] <= 105

代码结果

运行时间: 97 ms, 内存: 32.3 MB


/*
题目思路:
1. 使用Java Stream处理输入数组。
2. 寻找所有可能的子序列组合。
3. 验证每个子序列是否是方波。
4. 找出最长的方波长度。
*/

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class Solution {
    public int longestSquareWave(int[] nums) {
        List<Integer> sortedNums = IntStream.of(nums).sorted().boxed().collect(Collectors.toList());
        int maxLength = -1;
        for (int i = 0; i < sortedNums.size(); i++) {
            for (int j = i + 1; j < sortedNums.size(); j++) {
                int length = 1;
                int current = sortedNums.get(j);
                while (Math.sqrt(current) % 1 == 0 && sortedNums.contains((int)Math.sqrt(current))) {
                    length++;
                    current = (int) Math.sqrt(current);
                }
                if (length > 1) {
                    maxLength = Math.max(maxLength, length);
                }
            }
        }
        return maxLength == 1 ? -1 : maxLength;
    }
}

解释

方法:

本题解的思路是首先将数组转换为集合,以去除重复元素。然后遍历集合中的每个元素,对于每个元素 x,检查 x 的平方是否在集合中。如果在,就继续检查 x 的平方的平方,以此类推,直到找不到为止。这样可以找到以 x 开头的最长方波的长度。最后返回所有方波中的最大长度。

时间复杂度:

O(n log n)

空间复杂度:

O(n)

代码细节讲解

🦆
题解中提到将数组转换为集合以去除重复元素,这一步是否对最终结果有可能产生影响,例如如果原数组中重复的元素可以构成更长的方波呢?
将数组转换为集合以去除重复元素不会影响最终结果,因为方波的定义与元素的不同次方值有关,而不是元素的出现次数。每个元素不论出现多少次,其平方值不变。因此,即使原数组中有重复元素,这些重复元素的平方也会相同,不会构成更长的方波。集合的使用是为了方便查找元素是否存在,提高效率。
🦆
在计算每个元素的平方时,题解中没有明确是否考虑了数字溢出的问题,这在实际实现时应如何处理?
题解中确实未提及数字溢出的问题。在实际实现时,特别是在使用像Python这样的语言时,通常不需要处理整数溢出,因为Python的int类型可以处理非常大的整数。然而,在其他语言中,如C++或Java,应当考虑溢出的可能性,可以通过使用长整型(long或BigInteger)来避免溢出,或者在每次计算平方前检查x是否大于类型可存储的最大平方根,以防止溢出。
🦆
题解中使用了x *= x来计算平方,这种方法是否会导致忽略掉一些有效的方波序列,比如一个元素和它的平方不连续但仍在集合中的情况?
使用x *= x来计算平方可能会忽略掉一些有效的方波序列。例如,如果一个元素和它的平方之间存在其他数字的平方,这些序列将不会被考虑。这种方法只能检查连续平方的存在,而忽视了可能存在于集合中的间断平方。为了捕捉所有可能的方波序列,算法需要修改以检查集合中任何元素的平方,而不仅仅是连续的平方。
🦆
题解中提到的算法中,最长方波长度初始化为-1,但在实际代码实现中,是否需要有一个初始判断来确保至少存在一个合法的方波?
是的,最长方波长度初始化为-1是为了处理数组中不存在任何方波的情况。然而,在实际实现中,应当在返回结果前检查是否有至少一个方波被发现,如果没有任何方波(ans仍为-1),则应当返回0或其他标志值,表明没有找到有效的方波。这样可以确保算法正确表达方波不存在的情况。

相关问题