在特定范围内查找具有特定总和的数字的排列,直到 N
给定四个数字N 、 L 、 R和S ,任务是找到前N个自然数(基于 1 的索引)的排列,其总和为S从索引L到R 。如果有多个排列,则打印其中任何一个。否则,打印-1 。
例子:
Input: N = 6, L = 3, R = 5, S = 8
Output: 3 4 5 2 1 6
Explanation: The output permutation has 5 at index L and 1 at index R. The sum of the numbers from L to R is 8(5+2+1).
Input: N = 4, L = 2, R = 3, S = 2
Output: -1
Explanation: There does not exist any permutation in which the sum of numbers from index L to R is S.
方法:给定的问题可以通过使用贪心方法来解决,该方法基于假设X数必须从前N个自然数的排列中选择的观察,因此要使总和为S ,让最小和最大和X个数分别为minSum和maxSum ,则:
X = R – L + 1
minSum = X(X + 1)/2
maxSum = X(2*N + 1 – X)/2
因此,如果给定的总和S位于[minSum, maxSum]范围内,则存在一个排列,使得从L到R的所有数字的总和为S 。否则,不存在任何这样的排列。请按照以下步骤解决问题:
- 定义一个可能的函数(int x, int S, int N)并执行以下任务:
- 将变量minSum初始化为x*(x + 1)/2并将maxSum 初始化为(x * ((2*N) – x + 1))/2 。
- 如果S小于minSum或S大于maxSum则返回false 。否则,返回true 。
- 初始化变量,比如x为(R – L + 1) 。
- 如果函数possible(x, S, N)返回的值返回false,则打印-1并从函数返回。
- 否则,初始化一个向量v[]以存储给定段中存在的数字。
- 使用变量i遍历范围[N, 1]并执行以下任务:
- 如果S – i大于等于0并且函数possible(x – 1, S – i, i – 1)返回true ,则将S设置为(S – i)将x的值减1并将i进入向量v[] 。
- 如果S等于0 ,则跳出循环。
- 如果S不等于0 ,则打印-1并返回。
- 初始化一个向量,比如v1[]以存储给定段中不存在的数字。
- 使用变量i迭代范围[1, N]并初始化一个向量迭代器并使用 find() 检查元素i是否存在于向量v[]中。如果它不存在,则将其推入向量v1 。
- 将变量j和f初始化为0以打印结果。
- 使用变量i遍历范围[1, L)并打印v1[j]的值,并将j的值增加1 。
- 使用变量i遍历范围[L, R]并打印v[f]的值,并将f的值增加1 。
- 使用变量i遍历范围[R+1, N]并打印v1[j]的值,并将j的值增加1 。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Function to check if sum is possible
// with remaining numbers
bool possible(int x, int S, int N)
{
// Stores the minimum sum possible with
// x numbers
int minSum = (x * (x + 1)) / 2;
// Stores the maximum sum possible with
// x numbers
int maxSum = (x * ((2 * N) - x + 1)) / 2;
// If S lies in the range
// [minSum, maxSum]
if (S < minSum || S > maxSum) {
return false;
}
return true;
}
// Function to find the resultant
// permutation
void findPermutation(int N, int L,
int R, int S)
{
// Stores the count of numbers
// in the given segment
int x = R - L + 1;
// If the sum is not possible
// with numbers in the segment
if (!possible(x, S, N)) {
// Output -1
cout << -1;
return;
}
else {
// Stores the numbers present
// within the given segment
vector v;
// Iterate over the numbers from
// 1 to N
for (int i = N; i >= 1; --i) {
// If (S-i) is a positive non-zero
// sum and if it is possible to
// obtain (S-i) remaining numbers
if ((S - i) >= 0
&& possible(x - 1, S - i,
i - 1)) {
// Update sum S
S = S - i;
// Update required numbers
// in the segment
x--;
// Push i in vector v
v.push_back(i);
}
// If sum has been obtained
if (S == 0) {
// Break from the loop
break;
}
}
// If sum is not obtained
if (S != 0) {
// Output -1
cout << -1;
return;
}
// Stores the numbers which are
// not present in given segment
vector v1;
// Loop to check the numbers not
// present in the segment
for (int i = 1; i <= N; ++i) {
// Pointer to check if i is
// present in vector v or not
vector::iterator it
= find(v.begin(), v.end(), i);
// If i is not present in v
if (it == v.end()) {
// Push i in vector v1
v1.push_back(i);
}
}
// Point to the first elements
// of v1 and v respectively
int j = 0, f = 0;
// Print the required permutation
for (int i = 1; i < L; ++i) {
cout << v1[j] << " ";
j++;
}
for (int i = L; i <= R; ++i) {
cout << v[f] << " ";
f++;
}
for (int i = R + 1; i <= N; ++i) {
cout << v1[j] << " ";
j++;
}
}
return;
}
// Driver Code
int main()
{
int N = 6, L = 3, R = 5, S = 8;
findPermutation(N, L, R, S);
return 0;
}
Java
import java.util.ArrayList;
// Java program for the above approach
class GFG{
// Function to check if sum is possible
// with remaining numbers
public static boolean possible(int x, int S, int N)
{
// Stores the minimum sum possible with
// x numbers
int minSum = (x * (x + 1)) / 2;
// Stores the maximum sum possible with
// x numbers
int maxSum = (x * ((2 * N) - x + 1)) / 2;
// If S lies in the range
// [minSum, maxSum]
if (S < minSum || S > maxSum) {
return false;
}
return true;
}
// Function to find the resultant
// permutation
public static void findPermutation(int N, int L,
int R, int S)
{
// Stores the count of numbers
// in the given segment
int x = R - L + 1;
// If the sum is not possible
// with numbers in the segment
if (!possible(x, S, N)) {
// Output -1
System.out.print(-1);
return;
}
else {
// Stores the numbers present
// within the given segment
ArrayList v = new ArrayList<>();
// Iterate over the numbers from
// 1 to N
for (int i = N; i >= 1; --i) {
// If (S-i) is a positive non-zero
// sum and if it is possible to
// obtain (S-i) remaining numbers
if ((S - i) >= 0
&& possible(x - 1, S - i,
i - 1)) {
// Update sum S
S = S - i;
// Update required numbers
// in the segment
x--;
// Push i in vector v
v.add(i);
}
// If sum has been obtained
if (S == 0) {
// Break from the loop
break;
}
}
// If sum is not obtained
if (S != 0) {
// Output -1
System.out.print(-1);
return;
}
// Stores the numbers which are
// not present in given segment
ArrayList v1 = new ArrayList();
// Loop to check the numbers not
// present in the segment
for (int i = 1; i <= N; ++i) {
// Pointer to check if i is
// present in vector v or not
boolean it = v.contains(i);
// If i is not present in v
if (!it) {
// Push i in vector v1
v1.add(i);
}
}
// Point to the first elements
// of v1 and v respectively
int j = 0, f = 0;
// Print the required permutation
for (int i = 1; i < L; ++i) {
System.out.print(v1.get(j) + " ");
j++;
}
for (int i = L; i <= R; ++i) {
System.out.print(v.get(f) + " ");
f++;
}
for (int i = R + 1; i <= N; ++i) {
System.out.print(v1.get(j) + " ");
j++;
}
}
return;
}
// Driver Code
public static void main(String args[])
{
int N = 6, L = 3, R = 5, S = 8;
findPermutation(N, L, R, S);
}
}
// This code is contributed by saurabh_jaiswal.
Python3
# python program for the above approach
# Function to check if sum is possible
# with remaining numbers
def possible(x, S, N):
# Stores the minimum sum possible with
# x numbers
minSum = (x * (x + 1)) // 2
# Stores the maximum sum possible with
# x numbers
maxSum = (x * ((2 * N) - x + 1)) // 2
# If S lies in the range
# [minSum, maxSum]
if (S < minSum or S > maxSum):
return False
return True
# Function to find the resultant
# permutation
def findPermutation(N, L, R, S):
# Stores the count of numbers
# in the given segment
x = R - L + 1
# If the sum is not possible
# with numbers in the segment
if (not possible(x, S, N)):
# Output -1
print("-1")
return
else:
# Stores the numbers present
# within the given segment
v = []
# Iterate over the numbers from
# 1 to N
for i in range(N, 0, -1):
# If (S-i) is a positive non-zero
# sum and if it is possible to
# obtain (S-i) remaining numbers
if ((S - i) >= 0 and possible(x - 1, S - i, i - 1)):
# Update sum S
S = S - i
# Update required numbers
# in the segment
x -= 1
# Push i in vector v
v.append(i)
# If sum has been obtained
if (S == 0):
# Break from the loop
break
# If sum is not obtained
if (S != 0):
# Output -1
print(-1)
return
# Stores the numbers which are
# not present in given segment
v1 = []
# Loop to check the numbers not
# present in the segment
for i in range(1, N+1):
# Pointer to check if i is
# present in vector v or not
it = i in v
# If i is not present in v
if (not it):
# Push i in vector v1
v1.append(i)
# Point to the first elements
# of v1 and v respectively
j = 0
f = 0
# Print the required permutation
for i in range(1, L):
print(v1[j], end = " ")
j += 1
for i in range(L, R + 1):
print(v[f], end = " ")
f += 1
for i in range(R + 1, N + 1):
print(v1[j], end = " ")
j += 1
return
# Driver Code
if __name__ == "__main__":
N = 6
L = 3
R = 5
S = 8
findPermutation(N, L, R, S)
# This code is contributed by rakeshsahni
C#
// C# program for the above approach
using System;
using System.Collections.Generic;
class GFG {
// Function to check if sum is possible
// with remaining numbers
public static bool possible(int x, int S, int N)
{
// Stores the minimum sum possible with
// x numbers
int minSum = (x * (x + 1)) / 2;
// Stores the maximum sum possible with
// x numbers
int maxSum = (x * ((2 * N) - x + 1)) / 2;
// If S lies in the range
// [minSum, maxSum]
if (S < minSum || S > maxSum) {
return false;
}
return true;
}
// Function to find the resultant
// permutation
public static void findPermutation(int N, int L, int R,
int S)
{
// Stores the count of numbers
// in the given segment
int x = R - L + 1;
// If the sum is not possible
// with numbers in the segment
if (!possible(x, S, N)) {
// Output -1
Console.WriteLine(-1);
return;
}
else {
// Stores the numbers present
// within the given segment
List v = new List();
// Iterate over the numbers from
// 1 to N
for (int i = N; i >= 1; --i) {
// If (S-i) is a positive non-zero
// sum and if it is possible to
// obtain (S-i) remaining numbers
if ((S - i) >= 0
&& possible(x - 1, S - i, i - 1)) {
// Update sum S
S = S - i;
// Update required numbers
// in the segment
x--;
// Push i in vector v
v.Add(i);
}
// If sum has been obtained
if (S == 0) {
// Break from the loop
break;
}
}
// If sum is not obtained
if (S != 0) {
// Output -1
Console.WriteLine(-1);
return;
}
// Stores the numbers which are
// not present in given segment
List v1 = new List();
// Loop to check the numbers not
// present in the segment
for (int i = 1; i <= N; ++i) {
// Pointer to check if i is
// present in vector v or not
bool it = v.Contains(i);
// If i is not present in v
if (!it) {
// Push i in vector v1
v1.Add(i);
}
}
// Point to the first elements
// of v1 and v respectively
int j = 0, f = 0;
// Print the required permutation
for (int i = 1; i < L; ++i) {
Console.Write(v1[j] + " ");
j++;
}
for (int i = L; i <= R; ++i) {
Console.Write(v[f] + " ");
f++;
}
for (int i = R + 1; i <= N; ++i) {
Console.Write(v1[j] + " ");
j++;
}
}
return;
}
// Driver Code
public static void Main()
{
int N = 6, L = 3, R = 5, S = 8;
findPermutation(N, L, R, S);
}
}
// This code is contributed by ukasp.
Javascript
3 4 5 2 1 6
时间复杂度: O(N 2 )
辅助空间: O(N)