Java 中最长奇偶子序列

2024 年 9 月 10 日 | 阅读 7 分钟

Java 中最长奇偶子序列是一个问题,需要在一个大小为 s 的非负数组中找到一个子序列,该子序列以交替的方式包含奇偶数。因此,需要找到具有交替奇偶数序列的最长子序列中的元素数量。请注意,子序列可以以偶数或奇数开头。让我们通过一些例子来理解它。

例如

输入: int arr[] = {15, 16, 19, 14, 17, 18, 21, 30, 78}, //Size s = 9

输出 8

解释: 所需的最长子序列是 (15, 16, 19, 14, 17, 18, 21, 30) 或 (15, 16, 19, 14, 17, 18, 21, 78),子序列中的元素数量为 8。

输入: int arr[] = {11, 112, 12, 122, 15, 130, 131, 140, 117, 111}, //Size s = 10

输出 7

解释: 所需的最长子序列是 (11, 112, 15, 130, 131, 140, 117) 或 (11, 112, 15, 130, 131, 140, 111),或者可能还有其他子序列,子序列中的元素数量为 7。

方法

有两种方法可以找出最长的奇偶子序列。一种是暴力法,也称为朴素法。另一种是使用动态规划的高效方法。让我们从朴素法开始。

朴素方法

在这种方法中,我们将找出给定数组的所有可能子序列。然后,对于所有计算出的子序列,我们将过滤出最长的奇偶子序列。为了更好地理解,请观察以下程序。

文件名: OddEvenSeq.java

输出

For the input array: 
15 16 19 14 17 18 21 30 78 

The longest odd even subsequence is: 8

For the input array: 
11 112 12 122 15 130 131 140 117 111 

The longest odd even subsequence is: 7

复杂度分析: 在上述程序中,有两个选择;一个是包含该元素,另一个是排除该元素。因此,该程序的时间复杂度是指数级的,即 O(2n),其中 n 是数组中存在的元素总数。时间复杂度 O(2n) 非常大。因此,对于包含大量元素的输入数组,上述程序不适用。此外,程序占用了大量额外的空间,这也是指数级的 O(2n)。

实现:动态规划

设 longLen(j) 为以索引 j 结尾的最长奇偶子序列 (LOES) 的长度,使得 a[j] 是 LOES 的最后一个元素。因此,longLen(j) 可以递归地写为:longLen(j) = 1 + max(longLen(i)),其中 0 < i < j 且 (a[i] < a[j]) 且 (a[i]+a[j]) % 2 != 0;或者 longLen(j) = 1,如果不存在这样的 i。为了计算给定数组的最长奇偶子序列,需要返回 max(longLen(j)),其中 0 < j < size。

以下程序实现了上述递归关系中的动态规划方法。

文件名: OddEvenSeq1.java

输出

For the input array: 
15 16 19 14 17 18 21 30 78 

The longest odd even subsequence is: 8

复杂度分析: 上述程序使用了 2 级嵌套的 for 循环。因此,该程序的时间复杂度为 O(n2),其中 n 是数组中存在的元素总数。该程序使用数组作为额外的内存,大小为 n。因此,该程序的空间复杂度为 O(n)。