📌  相关文章
📜  从左侧只能看到 K 条的方式数

📅  最后修改于: 2021-09-17 16:15:22             🧑  作者: Mango

给定一个数K,和高度N个酒吧从1N,任务是找到方法来安排的N个条,使得仅退K棒是从左边可见数量。

例子

朴素的方法:朴素的方法是检查1 到 N 的所有排列,并检查从左侧可见的条形数量是否为K。

下面是上述方法的实现:

C++
// C++ program for the above approach
#include 
using namespace std;
 
// Function to calculate the number
// of bars that are visible from
// the left for a particular arrangement
int noOfbarsVisibleFromLeft(vector v)
{
    int last = 0, ans = 0;
    for (auto u : v)
 
        // If current element is greater
// than the last greater element,
// it is visible
        if (last < u) {
            ans++;
            last = u;
        }
    return ans;
}
 
// Function to calculate the number
// of rearrangements where
// K bars are visiblef from the left
int KvisibleFromLeft(int N, int K)
{
    // Vector to store current permutation
    vector v(N);
    for (int i = 0; i < N; i++)
        v[i] = i + 1;
    int ans = 0;
 
    // Check for all permutations
    do {
 
        // If current permutation meets
// the conditions, increment answer
        if (noOfbarsVisibleFromLeft(v) == K)
            ans++;
    } while (next_permutation(v.begin(), v.end()));
 
    return ans;
}
 
// Driver code
int main()
{
    // Input
    int N = 5, K = 2;
 
    // Function call
    cout << KvisibleFromLeft(N, K) << endl;
 
    return 0;
}


Python3
# Python3 program for the above approach
 
# Function to calculate the number
# of bars that are visible from
# the left for a particular arrangement
def noOfbarsVisibleFromLeft(v):
    last = 0
    ans = 0
 
    for u in v:
    # If current element is greater
    # than the last greater element,
    # it is visible
        if (last < u):
            ans += 1
            last = u
 
    return ans
 
def nextPermutation(nums):
    i = len(nums) - 2
    while i > -1:
        if nums[i] < nums[i + 1]:
            j = len(nums) - 1
            while j > i:
                if nums[j] > nums[i]:
                    break
                j -= 1
            nums[i], nums[j] = nums[j], nums[i]
            break
        i -= 1
    nums[i + 1:] = reversed(nums[i + 1:])
    return nums
   
# Function to calculate the number
# of rearrangements where
# K bars are visiblef from the left
def KvisibleFromLeft(N, K):
    # Vector to store current permutation
    v = [0]*(N)
    for i in range(N):
        v[i] = i + 1
    ans = 0
 
    temp = list(v)
 
    # Check for all permutations
    while True:
        # If current permutation meets
# the conditions, increment answer
        if (noOfbarsVisibleFromLeft(v) == K):
            ans += 1
        v = nextPermutation(v)
 
        if v == temp:
            break
 
    return ans
 
# Driver code
if __name__ == '__main__':
    # Input
    N = 5
    K = 2
 
    # Function call
    print (KvisibleFromLeft(N, K))
 
# This code is contributed by mohit kumar 29.


C++
// C++ implementation for the above approach
#include 
using namespace std;
 
// Function to calculate the number of permutations of
// N, where only K bars are visible from the left.
int KvisibleFromLeft(int N, int K)
{
 
    // Only ascending order is possible
    if (N == K)
        return 1;
 
    // N is placed at the first position
    // The nest N-1 are arranged in (N-1)! ways
    if (K == 1) {
        int ans = 1;
        for (int i = 1; i < N; i++)
            ans *= i;
        return ans;
    }
 
    // Recursing
    return KvisibleFromLeft(N - 1, K - 1)
           + (N - 1) * KvisibleFromLeft(N - 1, K);
}
// Driver code
int main()
{
    // Input
    int N = 5, K = 2;
 
    // Function call
    cout << KvisibleFromLeft(N, K) << endl;
    return 0;
}


Java
// Java program for the above approach
class GFG{
 
// Function to calculate the number of
// permutations of N, where only K bars
// are visible from the left.
static int KvisibleFromLeft(int N, int K)
{
     
    // Only ascending order is possible
    if (N == K)
        return 1;
 
    // N is placed at the first position
    // The nest N-1 are arranged in (N-1)! ways
    if (K == 1)
    {
        int ans = 1;
        for(int i = 1; i < N; i++)
            ans *= i;
             
        return ans;
    }
 
    // Recursing
    return KvisibleFromLeft(N - 1, K - 1) +
        (N - 1) * KvisibleFromLeft(N - 1, K);
}
 
// Driver code
public static void main(String[] args)
{
     
    // Input
    int N = 5, K = 2;
 
    // Function call
    System.out.println(KvisibleFromLeft(N, K));
}
}
 
// This code is contributed by abhinavjain194


Python3
# Python 3 implementation for the above approach
 
# Function to calculate the number of permutations of
# N, where only K bars are visible from the left.
def KvisibleFromLeft(N, K):
   
    # Only ascending order is possible
    if (N == K):
        return 1
 
    # N is placed at the first position
    # The nest N-1 are arranged in (N-1)! ways
    if (K == 1):
        ans = 1
        for i in range(1, N, 1):
            ans *= i
        return ans
 
    # Recursing
    return KvisibleFromLeft(N - 1, K - 1) + (N - 1) * KvisibleFromLeft(N - 1, K)
 
# Driver code
if __name__ == '__main__':
   
    # Input
    N = 5
    K = 2
 
    # Function call
    print(KvisibleFromLeft(N, K))
     
    # This code is contributed by ipg2016107.


C#
// C# program for the above approach
using System;
 
class GFG
{
 
// Function to calculate the number of
// permutations of N, where only K bars
// are visible from the left.
static int KvisibleFromLeft(int N, int K)
{
     
    // Only ascending order is possible
    if (N == K)
        return 1;
 
    // N is placed at the first position
    // The nest N-1 are arranged in (N-1)! ways
    if (K == 1)
    {
        int ans = 1;
        for(int i = 1; i < N; i++)
            ans *= i;
             
        return ans;
    }
 
    // Recursing
    return KvisibleFromLeft(N - 1, K - 1) +
        (N - 1) * KvisibleFromLeft(N - 1, K);
}
 
// Driver code
public static void Main(String[] args)
{
     
    // Input
    int N = 5, K = 2;
 
    // Function call
    Console.Write(KvisibleFromLeft(N, K));
}
}
 
// This code is contributed by shivanisinghss2110


Javascript


C++
// C++ implementation for the above approach
#include 
using namespace std;
 
// dp array
int dp[1005][1005];
 
// Function to calculate the number
// of permutations of N, where
// only K bars are visible from the left.
int KvisibleFromLeft(int N, int K)
{
    // If subproblem has already
// been calculated, return
    if (dp[N][K] != -1)
        return dp[N][K];
 
    // Only ascending order is possible
    if (N == K)
        return dp[N][K] = 1;
 
    // N is placed at the first position
    // The nest N-1 are arranged in (N-1)! ways
    if (K == 1) {
        int ans = 1;
        for (int i = 1; i < N; i++)
            ans *= i;
        return dp[N][K] = ans;
    }
 
    // Recursing
    return dp[N][K]
           = KvisibleFromLeft(N - 1, K - 1)
             + (N - 1) * KvisibleFromLeft(N - 1, K);
}
// Driver code
int main()
{
    // Input
    int N = 5, K = 2;
 
    // Initialize dp array
    memset(dp, -1, sizeof(dp));
 
    // Function call
    cout << KvisibleFromLeft(N, K) << endl;
    return 0;
}


C#
// C# implementation for the above approach
using System;
 
public class GFG{
 
// dp array
static int [,]dp = new int[1005, 1005];
 
// Function to calculate the number
// of permutations of N, where
// only K bars are visible from the left.
static int KvisibleFromLeft(int N, int K)
{
    // If subproblem has already
// been calculated, return
    if (dp[N ,K] != -1)
        return dp[N,K];
 
    // Only ascending order is possible
    if (N == K)
        return dp[N,K] = 1;
 
    // N is placed at the first position
    // The nest N-1 are arranged in (N-1)! ways
    if (K == 1) {
        int ans = 1;
        for (int i = 1; i < N; i++)
            ans *= i;
        return dp[N,K] = ans;
    }
 
    // Recursing
    return dp[N,K]
           = KvisibleFromLeft(N - 1, K - 1)
             + (N - 1) * KvisibleFromLeft(N - 1, K);
}
// Driver code
public static void Main(String[] args)
{
    // Input
    int N = 5, K = 2;
 
    // Initialize dp array
    for(int i = 0; i < 1005; i++)
  {
    for (int j = 0; j < 1005; j++)
    {
      dp[i, j] = -1;
    }
  }
  
    // Function call
    Console.Write( KvisibleFromLeft(N, K));
}
}
 
// This code is contributed by shivanisinghss2110


Javascript


Java
// Java implementation for the above approach
import java.util.*;
 
class GFG{
 
// dp array
static int [][]dp = new int[1005][1005];
 
// Function to calculate the number
// of permutations of N, where
// only K bars are visible from the left.
static int KvisibleFromLeft(int N, int K)
{
    // If subproblem has already
// been calculated, return
    if (dp[N][K] != -1)
        return dp[N][K];
 
    // Only ascending order is possible
    if (N == K)
        return dp[N][K] = 1;
 
    // N is placed at the first position
    // The nest N-1 are arranged in (N-1)! ways
    if (K == 1) {
        int ans = 1;
        for (int i = 1; i < N; i++)
            ans *= i;
        return dp[N][K] = ans;
    }
 
    // Recursing
    return dp[N][K]
           = KvisibleFromLeft(N - 1, K - 1)
             + (N - 1) * KvisibleFromLeft(N - 1, K);
}
// Driver code
public static void main(String[] args)
{
    // Input
    int N = 5, K = 2;
 
    // Initialize dp array
    for(int i = 0; i < 1005; i++)
  {
    for (int j = 0; j < 1005; j++)
    {
      dp[i][j] = -1;
    }
  }
  
    // Function call
    System.out.print( KvisibleFromLeft(N, K));
}
}
 
// This code is contributed by shivanisinghss2110


输出
50

时间复杂度: O(N!)
辅助空间: O(N)

有效的方法:有效的方法是使用递归。请按照以下步骤解决问题:

  • 创建一个递归函数KvisibleFromLeft() ,它将NK作为输入参数并执行以下操作:
    • 基本情况:
      • 如果N等于K ,则有一种排列条形的方法,即按升序排列。所以,返回1
      • 如果K==1 ,则有(N-1) 个!条的排列方式,因为最长的条放在第一个位置,剩余的N-1 个条可以放在剩余的N-1 个位置的任何位置。所以,返回(N-1)! .
    • 对于递归,有两种情况:
      • 可以将最小的条放在第一个位置,然后在剩余的N-1 个条中,只需要显示K-1 个条。因此,答案将与排列N-1 个条形以使K-1 个条形可见的方法数量相同。因此,这种情况会递归调用KvisibleFromLeft(N-1, K-1)
      • 最小的条可以放置在N-1 个位置中的任何一个,除了第一个。这将隐藏最小的条形,因此,答案将与排列N-1 个条形以使K 个条形可见的方法数量相同。因此,这种情况递归地调用(N-1)*KvisibleFromLeft(N-1,K)。

下面是上述方法的实现:

C++

// C++ implementation for the above approach
#include 
using namespace std;
 
// Function to calculate the number of permutations of
// N, where only K bars are visible from the left.
int KvisibleFromLeft(int N, int K)
{
 
    // Only ascending order is possible
    if (N == K)
        return 1;
 
    // N is placed at the first position
    // The nest N-1 are arranged in (N-1)! ways
    if (K == 1) {
        int ans = 1;
        for (int i = 1; i < N; i++)
            ans *= i;
        return ans;
    }
 
    // Recursing
    return KvisibleFromLeft(N - 1, K - 1)
           + (N - 1) * KvisibleFromLeft(N - 1, K);
}
// Driver code
int main()
{
    // Input
    int N = 5, K = 2;
 
    // Function call
    cout << KvisibleFromLeft(N, K) << endl;
    return 0;
}

Java

// Java program for the above approach
class GFG{
 
// Function to calculate the number of
// permutations of N, where only K bars
// are visible from the left.
static int KvisibleFromLeft(int N, int K)
{
     
    // Only ascending order is possible
    if (N == K)
        return 1;
 
    // N is placed at the first position
    // The nest N-1 are arranged in (N-1)! ways
    if (K == 1)
    {
        int ans = 1;
        for(int i = 1; i < N; i++)
            ans *= i;
             
        return ans;
    }
 
    // Recursing
    return KvisibleFromLeft(N - 1, K - 1) +
        (N - 1) * KvisibleFromLeft(N - 1, K);
}
 
// Driver code
public static void main(String[] args)
{
     
    // Input
    int N = 5, K = 2;
 
    // Function call
    System.out.println(KvisibleFromLeft(N, K));
}
}
 
// This code is contributed by abhinavjain194

蟒蛇3

# Python 3 implementation for the above approach
 
# Function to calculate the number of permutations of
# N, where only K bars are visible from the left.
def KvisibleFromLeft(N, K):
   
    # Only ascending order is possible
    if (N == K):
        return 1
 
    # N is placed at the first position
    # The nest N-1 are arranged in (N-1)! ways
    if (K == 1):
        ans = 1
        for i in range(1, N, 1):
            ans *= i
        return ans
 
    # Recursing
    return KvisibleFromLeft(N - 1, K - 1) + (N - 1) * KvisibleFromLeft(N - 1, K)
 
# Driver code
if __name__ == '__main__':
   
    # Input
    N = 5
    K = 2
 
    # Function call
    print(KvisibleFromLeft(N, K))
     
    # This code is contributed by ipg2016107.

C#

// C# program for the above approach
using System;
 
class GFG
{
 
// Function to calculate the number of
// permutations of N, where only K bars
// are visible from the left.
static int KvisibleFromLeft(int N, int K)
{
     
    // Only ascending order is possible
    if (N == K)
        return 1;
 
    // N is placed at the first position
    // The nest N-1 are arranged in (N-1)! ways
    if (K == 1)
    {
        int ans = 1;
        for(int i = 1; i < N; i++)
            ans *= i;
             
        return ans;
    }
 
    // Recursing
    return KvisibleFromLeft(N - 1, K - 1) +
        (N - 1) * KvisibleFromLeft(N - 1, K);
}
 
// Driver code
public static void Main(String[] args)
{
     
    // Input
    int N = 5, K = 2;
 
    // Function call
    Console.Write(KvisibleFromLeft(N, K));
}
}
 
// This code is contributed by shivanisinghss2110

Javascript


输出
50

时间复杂度: O(2 N )
辅助空间: O(1)

有效方法:上述递归可以记忆,因此可以使用动态规划,因为存在最佳子结构。

下面是上述方法的实现:

C++

// C++ implementation for the above approach
#include 
using namespace std;
 
// dp array
int dp[1005][1005];
 
// Function to calculate the number
// of permutations of N, where
// only K bars are visible from the left.
int KvisibleFromLeft(int N, int K)
{
    // If subproblem has already
// been calculated, return
    if (dp[N][K] != -1)
        return dp[N][K];
 
    // Only ascending order is possible
    if (N == K)
        return dp[N][K] = 1;
 
    // N is placed at the first position
    // The nest N-1 are arranged in (N-1)! ways
    if (K == 1) {
        int ans = 1;
        for (int i = 1; i < N; i++)
            ans *= i;
        return dp[N][K] = ans;
    }
 
    // Recursing
    return dp[N][K]
           = KvisibleFromLeft(N - 1, K - 1)
             + (N - 1) * KvisibleFromLeft(N - 1, K);
}
// Driver code
int main()
{
    // Input
    int N = 5, K = 2;
 
    // Initialize dp array
    memset(dp, -1, sizeof(dp));
 
    // Function call
    cout << KvisibleFromLeft(N, K) << endl;
    return 0;
}

C#

// C# implementation for the above approach
using System;
 
public class GFG{
 
// dp array
static int [,]dp = new int[1005, 1005];
 
// Function to calculate the number
// of permutations of N, where
// only K bars are visible from the left.
static int KvisibleFromLeft(int N, int K)
{
    // If subproblem has already
// been calculated, return
    if (dp[N ,K] != -1)
        return dp[N,K];
 
    // Only ascending order is possible
    if (N == K)
        return dp[N,K] = 1;
 
    // N is placed at the first position
    // The nest N-1 are arranged in (N-1)! ways
    if (K == 1) {
        int ans = 1;
        for (int i = 1; i < N; i++)
            ans *= i;
        return dp[N,K] = ans;
    }
 
    // Recursing
    return dp[N,K]
           = KvisibleFromLeft(N - 1, K - 1)
             + (N - 1) * KvisibleFromLeft(N - 1, K);
}
// Driver code
public static void Main(String[] args)
{
    // Input
    int N = 5, K = 2;
 
    // Initialize dp array
    for(int i = 0; i < 1005; i++)
  {
    for (int j = 0; j < 1005; j++)
    {
      dp[i, j] = -1;
    }
  }
  
    // Function call
    Console.Write( KvisibleFromLeft(N, K));
}
}
 
// This code is contributed by shivanisinghss2110

Javascript


Java

// Java implementation for the above approach
import java.util.*;
 
class GFG{
 
// dp array
static int [][]dp = new int[1005][1005];
 
// Function to calculate the number
// of permutations of N, where
// only K bars are visible from the left.
static int KvisibleFromLeft(int N, int K)
{
    // If subproblem has already
// been calculated, return
    if (dp[N][K] != -1)
        return dp[N][K];
 
    // Only ascending order is possible
    if (N == K)
        return dp[N][K] = 1;
 
    // N is placed at the first position
    // The nest N-1 are arranged in (N-1)! ways
    if (K == 1) {
        int ans = 1;
        for (int i = 1; i < N; i++)
            ans *= i;
        return dp[N][K] = ans;
    }
 
    // Recursing
    return dp[N][K]
           = KvisibleFromLeft(N - 1, K - 1)
             + (N - 1) * KvisibleFromLeft(N - 1, K);
}
// Driver code
public static void main(String[] args)
{
    // Input
    int N = 5, K = 2;
 
    // Initialize dp array
    for(int i = 0; i < 1005; i++)
  {
    for (int j = 0; j < 1005; j++)
    {
      dp[i][j] = -1;
    }
  }
  
    // Function call
    System.out.print( KvisibleFromLeft(N, K));
}
}
 
// This code is contributed by shivanisinghss2110
输出
50

时间复杂度: O(NK)
辅助空间: O(NK)

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程