Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何优化我的Langford序列函数?_C++_Algorithm_Recursion_Time Complexity_Dynamic Programming - Fatal编程技术网

C++ 如何优化我的Langford序列函数?

C++ 如何优化我的Langford序列函数?,c++,algorithm,recursion,time-complexity,dynamic-programming,C++,Algorithm,Recursion,Time Complexity,Dynamic Programming,这是我的代码,用于从成对的数字数组(112233->312132)中生成Langford序列。我想写一个递归函数,因为我无法在任何地方在线找到一个递归函数作为算法的自我改进练习。我的问题是,如何优化它?是否有一种方法可以将动态规划应用于此,并具有更好的时间/空间复杂性,重点是时间复杂性?我当前的运行时复杂性是O(n^2),空间复杂性是O(n)。在编写更简洁的代码方面,任何形式的帮助都是值得赞赏的。谢谢另外,这是一个P问题还是一个NP问题 #include <iostream> usi

这是我的代码,用于从成对的数字数组(112233->312132)中生成Langford序列。我想写一个递归函数,因为我无法在任何地方在线找到一个递归函数作为算法的自我改进练习。我的问题是,如何优化它?是否有一种方法可以将动态规划应用于此,并具有更好的时间/空间复杂性,重点是时间复杂性?我当前的运行时复杂性是O(n^2),空间复杂性是O(n)。在编写更简洁的代码方面,任何形式的帮助都是值得赞赏的。谢谢另外,这是一个P问题还是一个NP问题

#include <iostream>
using namespace std;

const int arrLen = 8;
const int seqLen = 8;

bool langfordSequence(int * arr, int indx, int *seq, int pos);
int main() {

    int arr[] = {1,1,2,2,3,3,4,4};
    int seq[] = {0,0,0,0,0,0,0,0};

    bool test = langfordSequence(arr, 0, seq, 0);

    if (test)
        cout << "Langford Sequence Successful: " << endl;
    else
        cout << "Langford Sequence Failed: " << endl;

    for (int i = 0; i < seqLen; i++)
    {
        cout << seq[i] << " ";
    }   
    return 0;
}

bool langfordSequence(int * arr, int indx, int *seq, int pos)
{

    if (indx >= arrLen - 1) //this means we've reached the end of the array
        return true;

    if (pos + arr[indx] + 1 >= seqLen)  //if the second part of the number is off the array
        return false;

    if (seq[pos] == 0 && seq[pos + arr[indx] + 1] == 0)
    {
        seq[pos] = arr[indx];
        seq[pos + arr[indx] + 1] = arr[indx];
        if (langfordSequence(arr, indx + 2, seq, 0))    //the current pair is good, go to the next one, start from the beginning
            return true;
        else
        {
            seq[pos] = 0;
            seq[pos + arr[indx] + 1] = 0;
            if (langfordSequence(arr, indx, seq, pos + 1))
                return true;
        }
    }
    else
    {
        if (langfordSequence(arr, indx, seq, pos + 1))  //current position is no good, try next position
            return true;
    }
}
#包括
使用名称空间std;
常数int arrLen=8;
常数int seqLen=8;
bool-langford序列(int*arr、int-indx、int*seq、int-pos);
int main(){
int arr[]={1,1,2,2,3,3,4,4};
int-seq[]={0,0,0,0,0,0,0};
布尔检验=朗福德序列(arr,0,seq,0);
如果(测试)

cout这是我在评论中提到的想法的伪代码。我还没有搜索到其他人做过类似的事情(因为我喜欢先自己解决问题),但其他人可能有优先权

朗福德算法 参数N(顶层,最终序列中的最大元素),M(中间,钩状序列中的最大元素)。在顶层,M=N。 返回:一个长度为2N的所有序列的列表,使得1..M中的每个元素j出现两次,以j个元素分隔,并且第二个M的位置小于N+M/2+1。序列的所有其他元素都设置为0

If M == 1 (base case)
  Let S' := []
  For i := 0 to N-2
    Let s' be the length 2N sequence containing the subsequence "101" starting at position i (counting from 0), and zero everywhere else.
    Insert s' into S'
  Return S'

Otherwise: (inductive case)
Let S' := []
Let S := LANGFORD(N,M-1)
For each s in S
  Let r := reverse(s)
  For i := 0 to floor(N - M/2 + 1)
    If s[i] == s[i+M+1] == 0
      Let s' be s with s'[i] and s'[i+M+1] replaced by M
      Insert s' into S'
    If r != s and r[i] == r[i+M+1] == 0
      Let r' be r with r'[i] and r'[i+M+1] replaced by M
      Insert r' into S'
Return S'
对N=4运行这个算法,我们首先得到M=4,然后递归到N=4,M=1。这一步给出了列表[[10100000]、[01010000]、[00101000]。我们将此返回到M=2步骤,该步骤找到钩子序列[[12102000]、[10120020]、[20020101]、[020020101]、[00201210]、[01210200]、[20021010]、[002012210]、[20121000]、[20121000]、[0201100]]将这些传递到M=3步骤,我们得到[[30023121]、[13120320]、[13102302]、[31213200]、[23021310]、[23121300]、[03121320]。最后,我们返回顶层函数并找到序列[[41312432]],它也表示其对称双23421314


从本质上说,我们正试图将每一块拼图拼成“30003”请记住,任何解决方案的镜像都是一个解决方案。时间和空间复杂性主要取决于N/2左右M值的潜在解决方案的组合爆炸。将序列存储为对齐的字节数组以使用向量指令,将列表存储为数组列表可能会很快(C++中的向量,Haskell等).

读过这个问题后,我想到的第一个想法是:如果你能列举低n的钩子序列,那么解决高n的问题就变成了看你是否能将两个元素插入正确大小的间隙中。钩子序列是像121_2或2_121一样的序列。要么有一个间隙,你可以插入一个3,得到312132或231213。问题空间中还有一个对称性,任何解的反面都是一个解。你确定你的算法在
O(n^2)
时间内运行吗?如果我正确理解你的算法,最坏的情况是你尝试将每个输入放在每个可能的位置,直到你找到一个解。那就是
O(2^n)
运行时间…@VincentvanderWeele你说得对,是O(2^n),我仍然掌握着测量时间复杂度的窍门。在递归算法中找出时间复杂度感觉很棘手。啊,这个算法太慢了!@Lorehead你的意思是,不要再从第一个位置开始,而是跟踪打开的位置,看看这些位置是否直接起作用?这在我脑海中已经出现,但我现在不会了要搜索数组以查找打开的插槽?也许我可以使用另一个数组来存储打开的插槽。例如,第一个元素存储第一个打开的插槽,第二个元素存储第二个打开的插槽,等等。但我仍然无法使其小于O(2^n),对吗?