📌  相关文章
📜  给定字符串的字典序最小 K 长度子序列

📅  最后修改于: 2021-09-04 11:39:40             🧑  作者: Mango

给定一个长度为N的字符串S ,任务是从字符串S (其中K < N )中找到字典序最小的K长度子序列。

例子:

朴素的方法:最简单的方法是从给定的字符串生成所有可能的长度为K的子序列,并将所有子序列存储在一个向量中。现在,对向量进行排序并在0位置打印字符串,以便按字典顺序排列最小的子序列。
时间复杂度: O(2 N )
辅助空间: O(1)

高效方法:为了优化上述方法,思想是堆栈数据结构,以递增顺序跟踪字符,以获得字典序最小的子序列。请按照以下步骤解决问题:

  • 初始化一个堆栈,比如answer ,这样在字符串 的任何索引处,堆栈应该包含直到当前索引的最小 K 长度子序列。
  • 遍历字符串并执行以下步骤:
    • 如果堆栈为空,则将当前字符压入堆栈。
    • 否则,迭代直到字符串S[i]的当前元素小于堆栈的顶部元素并不断从堆栈中弹出以确保堆栈的大小至多为K
    • 如果经过上述步骤堆栈的大小小于K ,则将当前字符压入堆栈。
  • 完成上述步骤后,将栈中存储的字符逆序打印,得到结果子序列字符串。

下面是上述方法的实现:

C++
// C++ program for the above approach
 
#include 
using namespace std;
 
// Function to find lexicographically
// smallest subsequence of size K
void smallestSubsequence(string& S, int K)
{
    // Length of string
    int N = S.size();
 
    // Stores the minimum subsequence
    stack answer;
 
    // Traverse the string S
    for (int i = 0; i < N; ++i) {
 
        // If the stack is empty
        if (answer.empty()) {
            answer.push(S[i]);
        }
        else {
 
            // Iterate till the current
            // character is less than the
            // the character at the top of stack
            while ((!answer.empty())
                   && (S[i] < answer.top())
 
                   // Check if there are enough
                   // characters remaining
                   // to obtain length K
                   && (answer.size() - 1 + N - i >= K)) {
                answer.pop();
            }
 
            // If stack size is < K
            if (answer.empty() || answer.size() < K) {
 
                // Push the current
                // character into it
                answer.push(S[i]);
            }
        }
    }
 
    // Stores the resultant string
    string ret;
 
    // Iterate until stack is empty
    while (!answer.empty()) {
        ret.push_back(answer.top());
        answer.pop();
    }
 
    // Reverse the string
    reverse(ret.begin(), ret.end());
 
    // Print the string
    cout << ret;
}
 
// Driver Code
int main()
{
    string S = "aabdaabc";
    int K = 3;
    smallestSubsequence(S, K);
 
    return 0;
}


Java
// Java program for the above approach
import java.util.*;
class GFG
{
 
  // Function to find lexicographically
  // smallest subsequence of size K
  static void smallestSubsequence(char []S, int K)
  {
 
    // Length of String
    int N = S.length;
 
    // Stores the minimum subsequence
    Stack answer = new Stack<>();
 
    // Traverse the String S
    for (int i = 0; i < N; ++i) {
 
      // If the stack is empty
      if (answer.isEmpty()) {
        answer.add(S[i]);
      }
      else {
 
        // Iterate till the current
        // character is less than the
        // the character at the top of stack
        while ((!answer.isEmpty())
               && (S[i] < answer.peek())
 
               // Check if there are enough
               // characters remaining
               // to obtain length K
               && (answer.size() - 1 + N - i >= K)) {
          answer.pop();
        }
 
        // If stack size is < K
        if (answer.isEmpty() || answer.size() < K) {
 
          // Push the current
          // character into it
          answer.add(S[i]);
        }
      }
    }
 
    // Stores the resultant String
    String ret="";
 
    // Iterate until stack is empty
    while (!answer.isEmpty()) {
      ret+=(answer.peek());
      answer.pop();
    }
 
    // Reverse the String
    ret = reverse(ret);
 
    // Print the String
    System.out.print(ret);
  }
  static String reverse(String input) {
    char[] a = input.toCharArray();
    int l, r = a.length - 1;
    for (l = 0; l < r; l++, r--) {
      char temp = a[l];
      a[l] = a[r];
      a[r] = temp;
    }
    return String.valueOf(a);
  }
 
  // Driver Code
  public static void main(String[] args)
  {
    String S = "aabdaabc";
    int K = 3;
    smallestSubsequence(S.toCharArray(), K);
  }
}
 
// This code is contributed by shikhasingrajput


Python3
# CPP program for the above approach
 
# Function to find lexicographically
# smallest subsequence of size K
def smallestSubsequence(S, K):
   
    # Length of string
    N = len(S)
 
    # Stores the minimum subsequence
    answer = []
 
    # Traverse the string S
    for i in range(N):
       
        # If the stack is empty
        if (len(answer) == 0):
            answer.append(S[i])
        else:
           
            # Iterate till the current
            # character is less than the
            # the character at the top of stack
            while (len(answer) > 0 and (S[i] < answer[len(answer) - 1]) and (len(answer) - 1 + N - i >= K)):
                answer = answer[:-1]
 
            # If stack size is < K
            if (len(answer) == 0 or len(answer) < K):
               
                # Push the current
                # character into it
                answer.append(S[i])
 
    # Stores the resultant string
    ret = []
 
    # Iterate until stack is empty
    while (len(answer) > 0):
        ret.append(answer[len(answer) - 1])
        answer = answer[:-1]
 
    # Reverse the string
    ret = ret[::-1]
    ret = ''.join(ret)
     
    # Print the string
    print(ret)
 
# Driver Code
if __name__ == '__main__':
    S = "aabdaabc"
    K = 3
    smallestSubsequence(S, K)
     
    # This code is contributed by SURENDRA_GANGWAR.


C#
// C# program for the above approach
using System;
using System.Collections.Generic;
public class GFG
{
 
  // Function to find lexicographically
  // smallest subsequence of size K
  static void smallestSubsequence(char []S, int K)
  {
 
    // Length of String
    int N = S.Length;
 
    // Stores the minimum subsequence
    Stack answer = new Stack();
 
    // Traverse the String S
    for (int i = 0; i < N; ++i) {
 
      // If the stack is empty
      if (answer.Count==0) {
        answer.Push(S[i]);
      }
      else {
 
        // Iterate till the current
        // character is less than the
        // the character at the top of stack
        while ((answer.Count!=0)
               && (S[i] < answer.Peek())
 
               // Check if there are enough
               // characters remaining
               // to obtain length K
               && (answer.Count - 1 + N - i >= K)) {
          answer.Pop();
        }
 
        // If stack size is < K
        if (answer.Count==0 || answer.Count < K) {
 
          // Push the current
          // character into it
          answer.Push(S[i]);
        }
      }
    }
 
    // Stores the resultant String
    String ret="";
 
    // Iterate until stack is empty
    while (answer.Count!=0) {
      ret+=(answer.Peek());
      answer.Pop();
    }
 
    // Reverse the String
    ret = reverse(ret);
 
    // Print the String
    Console.Write(ret);
  }
  static String reverse(String input) {
    char[] a = input.ToCharArray();
    int l, r = a.Length - 1;
    for (l = 0; l < r; l++, r--) {
      char temp = a[l];
      a[l] = a[r];
      a[r] = temp;
    }
    return String.Join("",a);
  }
 
  // Driver Code
  public static void Main(String[] args)
  {
    String S = "aabdaabc";
    int K = 3;
    smallestSubsequence(S.ToCharArray(), K);
  }
}
 
// This code is contributed by 29AjayKumar


Javascript


输出:
aaa

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

如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live