给定两个整数N和K ,任务是在执行最大K 次操作后,在前N 个自然数的序列中找到最大反演次数。在每个操作中,可以交换序列中的任意两个元素。注意:序列中的元素是按升序排列的,序列中没有重复的元素。
例子:
Input: N = 5, K = 3
Output: 10
Explanation:
Initially we have the sequence as {1, 2, 3, 4, 5}.
In the first operation, we can swap 1 and 5, so sequence becomes {5, 2, 3, 4, 1}.
In the second operation, we can swap 2 and 4, so sequence becomes {5, 4, 3, 2, 1}.
We don’t require any more operations. Thus, the number of inversions in the above sequence is 10
Input: N = 4, K = 1
Output: 5
Explanation:
Initially we have the sequence as { 1, 2, 3, 4}.
In the first operation we can swap 1 and 4, so the sequence becomes {4, 2, 3, 1 }.
Since we can perform only 1 operation, so this is our final sequence. Thus, the number of inversions in the above sequence is 5.
方法:
- 因为按升序排列的元素是完美的,即它有0倒置,而按降序排列的元素是最不完美的,即它有最大的倒置。
- 因此,我们的想法是使每个交换操作的序列更接近降序,以获得最大的反转。因此,在第一次操作中,我们需要交换最大和最小元素。同样,在第i 个操作中,我们需要将第 i 个最大的元素与序列的第 i 个最小的元素交换。
- 将升序转换为降序所需的交换次数为N/2 。因此,执行的操作次数应小于或等于N/2 。
因此将 K 更新为:
K = min ( K, N / 2 )
- 我们需要维护两个变量‘left’和‘right’分别表示序列的第 i 个最小元素和第 i 个最大元素。
- 将‘left’初始化为1 ,将‘right’初始化为N 。
- 我们需要执行以下操作,直到K变为 0:
- On,在反转的序列号中交换‘左’和‘右’增加
2 * ( left – right ) – 1
- 因此,将此值添加到答案中。
- 这是因为当我们交换 ‘left’ 和 ‘right’ 时,形式 (right, i) 的所有对都有助于反转,而且形式 (i, left) 的所有对都有助于反转,其中 left < i <正确的。
- 形式对的总数(right, i) => right – left, where left <= i < right
- (i, left) => right – left 形式的对的总数,其中 left< i <=right
- 此类对的总数为2 * ( right – left )
- 我们从中减去 1,因为在上面的计算中,对(右,左)被计算了两次。
- 将K和“右”的值减少1 ,将“左”的值增加 1。
- 打印答案的值
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Function which computes the
// maximum number of inversions
int maximum_inversion(int n, int k)
{
// 'answer' will store the required
// number of inversions
int answer = 0;
// We do this because we will
// never require more than
// floor(n/2) operations
k = min(k, n / 2);
// left pointer in the array
int left = 1;
// right pointer in the array
int right = n;
// Doing k operations
while (k--) {
// Incrementing ans by number
// of inversions increase due
// to this swapping
answer += 2 * (right - left) - 1;
left++;
right--;
}
cout << answer << endl;
}
// Driver code
int main()
{
// Input 1
int N = 5;
int K = 3;
maximum_inversion(N, K);
// Input 2
N = 4;
K = 1;
maximum_inversion(N, K);
return 0;
}
Java
// Java program for the above approach
import java.util.*;
class GFG{
// Function which computes the
// maximum number of inversions
static void maximum_inversion(int n, int k)
{
// 'answer' will store the required
// number of inversions
int answer = 0;
// We do this because we will
// never require more than
// floor(n/2) operations
k = Math.min(k, n / 2);
// left pointer in the array
int left = 1;
// right pointer in the array
int right = n;
// Doing k operations
while (k != 0)
{
k--;
// Incrementing ans by number
// of inversions increase due
// to this swapping
answer += 2 * (right - left) - 1;
left++;
right--;
}
System.out.println(answer);
}
// Driver Code
public static void main(String s[])
{
// Input 1
int N = 5;
int K = 3;
maximum_inversion(N, K);
// Input 2
N = 4;
K = 1;
maximum_inversion(N, K);
}
}
// This code is contributed by rutvik_56
Python3
# Python3 program for the above approach
# Function which computes the
# maximum number of inversions
def maximum_inversion(n, k):
# 'answer' will store the required
# number of inversions
answer = 0;
# We do this because we will
# never require more than
# floor(n/2) operations
k = min(k, n // 2);
# left pointer in the array
left = 1;
# right pointer in the array
right = n;
# Doing k operations
while (k > 0):
k -= 1;
# Incrementing ans by number
# of inversions increase due
# to this swapping
answer += 2 * (right - left) - 1;
left += 1;
right -= 1;
print(answer);
# Driver Code
if __name__ == '__main__':
# Input 1
N = 5;
K = 3;
maximum_inversion(N, K);
# Input 2
N = 4;
K = 1;
maximum_inversion(N, K);
# This code is contributed by amal kumar choubey
C#
// C# program for the above approach
using System;
class GFG{
// Function which computes the
// maximum number of inversions
static void maximum_inversion(int n, int k)
{
// 'answer' will store the required
// number of inversions
int answer = 0;
// We do this because we will
// never require more than
// floor(n/2) operations
k = Math.Min(k, n / 2);
// left pointer in the array
int left = 1;
// right pointer in the array
int right = n;
// Doing k operations
while (k != 0)
{
k--;
// Incrementing ans by number
// of inversions increase due
// to this swapping
answer += 2 * (right - left) - 1;
left++;
right--;
}
Console.WriteLine(answer);
}
// Driver Code
public static void Main(String []s)
{
// Input 1
int N = 5;
int K = 3;
maximum_inversion(N, K);
// Input 2
N = 4;
K = 1;
maximum_inversion(N, K);
}
}
// This code is contributed by Rohit_ranjan
Javascript
10
5
时间复杂度: O(K)
辅助空间: O(1)
如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live