【发布时间】:2020-09-19 09:46:23
【问题描述】:
我正在解决这个挑战: https://www.hackerrank.com/challenges/permutations-of-strings/problem
我正在使用这个算法: https://en.wikipedia.org/wiki/Permutation#Generation_in_lexicographic_order
假设我输入的字符串数组为{"a", "b", "c"},那么输出应该是:
a b c
a c b
b c a
c b a
b a c
c a b
因为有 3 个不同的字符串,所以有 3 个! = 6 个排列。
程序也是要处理重复的,所以如果我输入{"a", "b", "b"},就只有3个! /2! = 3 个排列。
无论如何,当我的程序到达c b a 时,它就会退出。为什么?我该如何解决?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void swap(char** s1, char** s2) // to swap two strings
{
char* temp = *s1;
*s1 = *s2;
*s2 = temp;
}
int next_permutation(int n, char **s)
{
/**
* Complete this method
* Return 0 when there is no next permutation and 1 otherwise
* Modify array s to its next permutation
*/
int k, i, l;
k = i = l = 0;
for(i = n - 2; i >= 0; i--) // first step
if(strcmp(s[i], s[i + 1]) < 0) {
k = i;
break;
}
if(i == -1)
return 0;
for(i = n - 1; i >= k + 1; i--) // second step
if(strcmp(s[k], s[i]) < 0) {
l = i;
break;
}
swap(&s[k], &s[l]); // third step
for(i = k + 1; i < n / 2; i++) // fourth step
swap(&s[i], &s[n - i - 1]);
return 1;
}
int main() // locked code
{
char **s;
int n;
scanf("%d", &n);
s = calloc(n, sizeof(char*));
for (int i = 0; i < n; i++)
{
s[i] = calloc(11, sizeof(char));
scanf("%s", s[i]);
}
do
{
for (int i = 0; i < n; i++)
printf("%s%c", s[i], i == n - 1 ? '\n' : ' ');
} while (next_permutation(n, s));
for (int i = 0; i < n; i++)
free(s[i]);
free(s);
return 0;
}
【问题讨论】:
-
与你所说的相反,你的程序只是输出
a b c然后退出。这是因为你在完全错误的时间打破了这些循环。 -
在 Xcode 上,当我输入 3、a、b、c 时,每个都在一个新行上,我得到输出,直到
c b a然后它重复。无论如何我该怎么办? -
请edit 您的问题直接在此处提供附加信息,而不是将其隐藏在 cmets 中。一个好的minimal reproducible example 需要几对相关不同的样本输入以及结果输出。
-
如果这是真的,那么“Xcode”就坏了。
strcmp(s[i], s[i + 1]) < 0对于a b c的初始数组永远不应该为真,因此循环将一直持续到i == n - 1,这意味着您返回0。在进行任何排列之前。你认为我更信任谁,Xcode 还是你? -
我将为第一步提供以下提示:从最大索引开始并向后工作是否有意义,因为您希望最大索引匹配条件?这样,您可以更快地退出循环......如果您将
k初始化为一个它不可能最终的值,那么您可以检查k是否仍然具有该值以确定条件是否曾经是的。