查找最大的排序选择

时间:2018-07-08 09:29:10

标签: arrays algorithm dynamic-programming lis

示例:给定[1 2 3 10 7 8 9],我正在寻找一种给出[1 1 1 0 1 1 1]的算法。

我有一个未排序的数组作为输入。作为输出,我寻找最大的排序选择。

  • 用“ 选择”表示具有1和0(如果选择或不选择元素)的相同长度的数组。
  • 具有“ 已排序”的意思是,所选元素构成一个已排序的数组-在上面的示例中:[1 2 3 7 8 9]。
  • 用“ 最大”表示没有排序的选择,其中有更多的1。

最坏的情况:我必须尝试所有2 ^ {0,1}个可能的选择。有没有更快的算法可以做到这一点?我不记得CS学习中的任何内容,也无法在线找到任何内容(至少使用我的措辞)。

3 个答案:

答案 0 :(得分:1)

是的,这可以通过动态编程解决。

您必须创建另一个长度等于给定数组的对数组,让我们将其命名为arr

arr [index]将存储子数组的最大长度,从而如果考虑到namedArray [0 ... index]中的数组及其后的namedArray [index]元素,则givenArray [index]是排序后的最后一个元素已添加。

从arr中,您可以找到子排序数组的最大长度并创建数组。

for (int i = 0;i<givenArray.size(); i++) {

    int after = -1;
    int length = 0;
    for(int j = 0;j<i;j++) {
        if (givenArray[j] < givenArray[i] && length < arr[j].maxLengthTillNow) {
            length = arr[j].maxLengthTillNow;
            after = j;
        }
    }

    arr[i].maxLengthTillNow = length + 1;
    arr[i].after = j;
}

复杂度:n * n

答案 1 :(得分:0)

在这里,我编写了一种方法 largestSortedSelection ,该方法将元素的向量作为输入(例如[1 2 3 10 7 8 9]),并返回布尔值向量,其中true / false表示1/0指示是否选择答案索引(例如[1 1 1 0 1 1 1 1])。

vector< bool >largestSortedSelection( vector<int>&v ){
int n = v.size(); 
vector< int >selectedLen(n);
vector< int >sortedList;
int maxLen = 1;
for(int i = 0; i<n; ++i){
    int lb = lower_bound(sortedList.begin(),sortedList.end(),v[i])-sortedList.begin();
    if( lb!=(int)sortedList.size() ){
        selectedLen[i]=lb+1;
        sortedList[lb]=v[i];
    }
    else {
        sortedList.push_back(v[i]);
        selectedLen[i]=(int)sortedList.size();
    }
    maxLen =  max( maxLen, selectedLen[i] );
}
int lst = INT_MAX;//assuming maximum element will be less than INT_MAX
int len = maxLen+1;
vector< bool >selection(n,0);
for(int i = n-1; i>=0; --i ){
    if( v[i]<lst && selectedLen[i]+1 == len ){
        selection[i] = 1;
        lst = v[i];
        len--;
    }
  }
  return selection;
}

在这种方法中:

  • selectedLen(i):最长到索引i的排序列表的长度。

  • sortedList:以递增的形式保存元素。

  • 选择:以0/1的形式保存答案
  • sortedList中的lower_bound函数:返回等于或大于等于的第一个元素。

如果您在理解源代码时遇到困难,请告诉我。
由于我在循环中使用了N次Lower_bound函数(其复杂度为logN)。因此,总体时间复杂度为: O(N logN)
内存复杂度将为 O(N),因为我正在使用内存来存储N个元素。

答案 2 :(得分:0)

感谢大家的帮助。这是我最后得到的Wikipedia伪代码的C ++实现:

/// Return indice of the a longest increasing subsequence.
/// implementation of https://en.wikipedia.org/wiki/Longest_increasing_subsequence
template<class T>
std::vector<size_t> indiceOfLongesIncreasingSubsequence(const std::vector<T>& v)
{
  std::vector<size_t> P(v.size()), M(v.size() + 1);
  size_t L = 0;
  for(size_t i = 0; i < v.size(); ++i)
  {
    // binary search for the largest positive j <= L such that v[M[j]] < v[i]
    size_t lo = 1, hi = L;
    while(lo <= hi)
    {
      size_t mid = (lo + hi)/2;
      if(v[M[mid]] < v[i])
        lo = mid+1;
      else
        hi = mid-1;
    }

    // predecessor of v[i] is the last index of the subsequence of length lo-1
    P[i] = M[lo-1];
    M[lo] = i;

    if(lo > L)
      L = lo;
  }

  // reconstruct the longest increasing subsequence
  std::vector<size_t> ind(L);
  size_t k = M[L];
  for(size_t i = 0; i < L; ++i)
  {
    ind[L-1-i] = k;
    k = P[k];
  }

  return ind;
}

要获取真/假向量,需要:

vector<bool> selection(ind.size(), false);
for(size_t i: ind)
  selection[i] = true;