从数组中删除最小元素,使得没有三个连续元素增加或减少
给定一个包含n 个不同正整数的数组。任务是找到要删除的最小元素数,以使数组中的三个连续元素都不会增加或减少。也就是说,在删除 a i – 1 > a i < a i + 1或 a i – 1 < a i > a i + 1之后。
例子 :
Input : arr[] = {5, 2, 3, 6, 1}
Output : 1
Given arr[] is not in required form
(2 < 3 < 6). So, after removal of
6 or 3, array will be in required manner.
Input : arr[] = { 4, 2, 6, 3, 10, 1}
Output : 0
请注意,对于 n < 3,输出将为 0,因为不需要删除任何元素。
方法1 O(n 2 ):
如果我们仔细观察,我们可以注意到在从 arr 中删除元素之后,剩下的是 arr 的锯齿形子序列。假设新数组是 arr'。那么我们为到达 arr' 而执行的删除次数就是 arr 的大小 - arr' 的大小。我们的目标是尽量减少这种差异。注意 arr 的大小是固定的,所以我们必须最小化 -arr' 的大小或最大化 arr' 的大小。因此问题被归结为寻找最长之字形子序列。
方法2 O(n):(棘手)
要删除的元素是那些 a i使得
a i-1 > a i > a i+1或
a i-1 < a i < a i+1
所以,计算所有那些 a i 。
这是如何运作的?
让我们定义一个i为,
如果 0 < i < n – 1 和 a i – 1 < a i < a i + 1 ,则达到峰值。
如果 0 < i < n – 1 和 a i – 1 > a i > a i + 1 ,则为谷。
令 P(arr) 和 V(arr) 分别为峰数和谷数。
观察,在任何 zigzag 阵列中,除了端点之外的所有元素都是峰值或谷值,即 n = P(arr) + V(arr) + 2。
现在,我们可以证明任何删除都不会增加任何数组中的峰和谷的总数:
1. 假设我们移除一个既不是峰也不是谷的元素ai :
- 如果 a i是端点,则显然不能形成峰或谷。
- 如果 a i – 1 < a i < a i + 1 ,则在删除 a i后,元素 a i – 1和 a i + 1将变得相邻。但是由于 a i – 1 < a i + 1 , a i – 1或 a i + 1的状态不会改变,即如果 a i – 1或 a i + 1最初是峰/谷/都不是,那么它将不会改变移除后保持峰值/谷值/两者都不是,因为它们与邻居的比较是相同的。特别是没有形成新的高峰或低谷。
- 与 a i – 1 > a i > a i + 1的情况类似。
2. 假设我们移除一个峰或谷:
- 假设我们移除一个峰值,所以 a i – 1 < a i > a i + 1 。现在,a i – 1或 a i + 1可能会变成峰或谷。但是我们可以证明它们不能同时改变,因为要么 a i - 1 < a i + 1 ,这意味着 a i - 1状态永远不会改变,要么 a i - 1 > a i + 1 ,这意味着 a i + 1状态永不改变。因此,最多会形成一个峰或谷,但由于我们移除了一个峰,因此峰/谷的总数不会增加。
- 当我们移除一个山谷时,同样的事情也会发生,即 a i – 1 > a i < a i + 1 。
因此任何删除都不会改变 P(arr) + V(arr)。
使用这个论点,我们可以说 arr 的最长 zigzag 子序列的长度最多为 P(arr) + V(arr) + 2。
另一方面,arr 有一个长度为 P(arr) + V(arr) + 2 的锯齿形子序列,即 arr 的峰、谷、端点的序列。可以证明这个子序列是 zigzag(通过尝试一些例子),因此最长的 zigzag 子序列的长度至少为 P(arr) + V(arr) + 2。所以,从前两个参数我们可以说最长的 zigzag子序列的精确长度为 P(arr) + V(arr) + 2。
因此,我们问题的答案是 arr - P(arr) - V(arr) - 2 的大小。
算法 :
1. Initialize count = 0.
2. For each element arr[i] from index i = 1 to n - 2.
(i) if (arr[i-1] arr[i+1])
(ii) increment count by 1.
3. return count.
C++
// C++ program to find minimum
// elements to be removed so
// that array becomes zig-zag.
#include
using namespace std;
int minimumDeletions(int a[],
int n)
{
if (n <= 2)
return 0;
// If number of element
// is greater than 2.
int count = 0;
for (int i = 0; i < n - 2; i++)
{
// If three element are
// consecutively increasing
// or decreasing.
if ((a[i] < a[i + 1] &&
a[i + 1] < a[i + 2]) ||
(a[i] > a[i + 1] &&
a[i + 1] > a[i + 2]))
count++;
}
return count;
}
// Driver Code
int main()
{
int a[] = { 5, 2, 3, 6, 1 };
int n = sizeof(a) / sizeof(a[0]);
cout << minimumDeletions(a, n)
<< endl;
return 0;
}
Java
// Java program to find minimum
// elements to be removed so that
// array becomes zig-zag.
class GFG
{
static int minimumDeletions(int a[],
int n)
{
if (n <= 2)
return 0;
// If number of element
// is greater than 2.
int count = 0;
for (int i = 0; i < n - 2; i++)
{
// If three element are
// consecutively increasing
// or decreasing.
if ((a[i] < a[i + 1] &&
a[i + 1] < a[i + 2]) ||
(a[i] > a[i + 1] &&
a[i + 1] > a[i + 2]))
count++;
}
return count;
}
// Driver Code
public static void main (String[] args)
{
int a[] = { 5, 2, 3, 6, 1 };
int n = a.length;
System.out.println(minimumDeletions(a, n));
}
}
Python3
# Python3 program to find minimum
# elements to be removed so that
# array becomes zig-zag.
def minimumDeletions(a, n):
if (n <= 2):
return 0
# If number of element is
# greater than 2.
count = 0
for i in range(n - 2):
# If three element are
# consecutively increasing
# or decreasing.
if ((a[i] < a[i + 1] and
a[i + 1] < a[i + 2]) or
(a[i] > a[i + 1] and
a[i + 1] > a[i + 2])):
count += 1
return count
# Driver Code
a = [ 5, 2, 3, 6, 1 ]
n = len(a)
print(minimumDeletions(a, n))
# This code is contributed
# by Anant Agarwal.
C#
// C# program to find minimum
// elements to be removed so
// that array becomes zig-zag.
using System;
class GFG
{
static int minimumDeletions(int []a,
int n)
{
if (n <= 2)
return 0;
// If number of element is
// greater than 2.
int count = 0;
for (int i = 0; i < n - 2; i++)
{
// If three element are
// consecutively increasing
// or decreasing.
if ((a[i] < a[i + 1] &&
a[i + 1] < a[i + 2]) ||
(a[i] > a[i + 1] &&
a[i + 1] > a[i + 2]))
count++;
}
return count;
}
// Driver Code
public static void Main ()
{
int []a = { 5, 2, 3, 6, 1 };
int n = a.Length;
Console.Write(minimumDeletions(a, n));
}
}
// This code is contributed
// by nitin mittal
PHP
$a[$i + 1] &&
$a[$i + 1] > $a[$i + 2]))
$count++;
}
return $count;
}
// Driver Code
{
$a = array( 5, 2, 3, 6, 1 );
$n = sizeof($a) / sizeof($a[0]);
echo minimumDeletions($a, $n) ;
return 0;
}
// This code is contributed
// by nitin mittal.
?>
Javascript
输出:
1