给定两个整数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:
- 开启时,将反转序列号中的“左”和“右”交换增加
2 * ( left – right ) – 1
因此,将此值添加到答案中。
- 这是因为当我们交换’left’和’right’时,所有形式的对(right,i)都会对反转产生影响,而且所有形式的对(i,left)都会对反转产生影响,其中left
- 形式对的总数(右,i) =>右–左,其中左<= i <右
- 形式对的总数(i,左) =>右–左,其中left
- 此类对的总数为2 *(右–左)
- 我们从中减去1,因为在上述计算中该对(右,左)被计数了两次。
- 这是因为当我们交换’left’和’right’时,所有形式的对(right,i)都会对反转产生影响,而且所有形式的对(i,left)都会对反转产生影响,其中left
- 将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
10
5
时间复杂度: O(K)
辅助空间: O(1)