📜  从词法上讲C++中的下一个排列

📅  最后修改于: 2021-05-30 06:37:13             🧑  作者: Mango

给定一个单词,在字典上找到更大的排列。例如,按字典顺序,“ gfg”的下一个排列是“ ggf”,“ acb”的下一个排列是“ bac”。

注意:在某些情况下,下一个在字典上更大的单词可能不存在,例如,“ aaa”和“ edcba”

在C++中,有一个特定的函数使我们免于编写大量代码。它在文件#include 中。该函数是next_permutation(a.begin(),a.end())。如果函数可以将对象重新排列为字典顺序更大的排列,则返回“ true”。否则,该函数返回“ false”。

让我们在这里看一下代码片段:

// Find the next lexicographically
// greater permutation of a word
  
#include 
#include 
  
using namespace std;
  
int main()
{
    string s = { "gfg" };
    bool val
        = next_permutation(s.begin(),
                           s.end());
    if (val == false)
        cout << "No Word Possible"
             << endl;
    else
        cout << s << endl;
    return 0;
}
输出:
ggf

无需使用STL也可以实现相同的程序。以下是相同的代码段。该想法基于以下事实:
1)以降序排列的序列没有下一个排列。例如,“ edcba”没有下一个排列。
2)对于未按降序排序的序列,例如“ abedc”,我们可以执行以下步骤。
……….a)从右向后移动并找到不遵循降序排列的第一项。例如,在“ abedc”中,字符“ b”不遵循降序排列。
………….b)交换找到的字符,在其右侧具有最近的最大(或最小的更大)元素。在“ abedc”的情况下,我们将“ c”作为最接近的较大元素。交换“ b”和“ c”后,字符串变为“ acedb”。
……….c)交换之后,在步骤a中找到的字符位置之后对字符串进行排序。在对“ acedb”的子字符串“ edb”进行排序之后,我们得到“ acbde ”,这是所需的下一个排列。

步骤b)和c)中的优化
a)由于序列是按降序排序的,因此我们可以使用二进制搜索来找到最接近的较大元素。
c)由于该序列已经按降序排序(即使在交换后,如我们与最接近的较大序列交换),我们也可以在反转序列后将其排序(以升序排序)。

// Find the next lexicographically
// greater permutation of a word
  
#include 
  
using namespace std;
  
void swap(char* a, char* b)
{
    if (*a == *b)
        return;
    *a ^= *b;
    *b ^= *a;
    *a ^= *b;
}
void rev(string& s, int l, int r)
{
    while (l < r)
        swap(&s[l++], &s[r--]);
}
  
int bsearch(string& s, int l, int r, int key)
{
    int index = -1;
    while (l <= r) {
        int mid = l + (r - l) / 2;
        if (s[mid] <= key)
            r = mid - 1;
        else {
            l = mid + 1;
            if (index == -1 || s[index] >= s[mid])
                index = mid;
        }
    }
    return index;
}
  
bool nextpermutation(string& s)
{
    int len = s.length(), i = len - 2;
    while (i >= 0 && s[i] >= s[i + 1])
        --i;
    if (i < 0)
        return false;
    else {
        int index = bsearch(s, i + 1, len - 1, s[i]);
        swap(&s[i], &s[index]);
        rev(s, i + 1, len - 1);
        return true;
    }
}
  
// Driver code
int main()
{
    string s = { "gfg" };
    bool val = nextpermutation(s);
    if (val == false)
        cout << "No Word Possible" << endl;
    else
        cout << s << endl;
    return 0;
}
// This code is contributed by Mysterious Mind
输出:
ggf

时间复杂度:

  1. 在最坏的情况下,next_permutation的第一步需要O(n)的时间。
  2. 二进制搜索需要O(logn)时间。
  3. 反向需要O(n)时间。

总时间复杂度为O(n)。
其中n是字符串的长度。

参考: http : //www.cplusplus.com/reference/algorithm/next_permutation/

要从最佳影片策划和实践问题去学习,检查了C++基础课程为基础,以先进的C++和C++ STL课程基础加上STL。要完成从学习语言到DS Algo等的更多准备工作,请参阅“完整面试准备课程”