📌  相关文章
📜  在特定范围内查找具有特定总和的数字的排列,直到 N

📅  最后修改于: 2022-05-13 01:56:06.189000             🧑  作者: Mango

在特定范围内查找具有特定总和的数字的排列,直到 N

给定四个数字NLRS ,任务是找到前N个自然数(基于 1 的索引)的排列,其总和为S从索引LR 。如果有多个排列,则打印其中任何一个。否则,打印-1

例子:

方法:给定的问题可以通过使用贪心方法来解决,该方法基于假设X数必须从前N个自然数的排列中选择的观察,因此要使总和为S ,让最小和最大和X个数分别为minSummaxSum ,则:

因此,如果给定的总和S位于[minSum, maxSum]范围内,则存在一个排列,使得从LR的所有数字的总和为S 。否则,不存在任何这样的排列。请按照以下步骤解决问题:

  • 定义一个可能的函数(int x, int S, int N)并执行以下任务:
    • 将变量minSum初始化为x*(x + 1)/2并将maxSum 初始化(x * ((2*N) – x + 1))/2
    • 如果S小于minSumS大于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
  • 将变量jf初始化为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)