Skip to content

Instantly share code, notes, and snippets.

@superlayone
Last active August 29, 2015 14:04
Show Gist options
  • Select an option

  • Save superlayone/e5d3d520322c7af33805 to your computer and use it in GitHub Desktop.

Select an option

Save superlayone/e5d3d520322c7af33805 to your computer and use it in GitHub Desktop.
从一列数中筛除尽可能少的数使得从左往右看,这些数是从小到大再从大到小的

##LIS变种

从一列数中筛除尽可能少的数使得从左往右看,这些数是从小到大再从大到小的(网易)

###思路

  • 双 LIS 问题,用DP可解,目标规划函数 max{ l[i] + r[i]}, 其中

     l[i] 为从左到右, 0 ~ i 个数之间满足递增的数字个数
     r[i] 为从右到左, n-1 ~ i 个数之间满足递增的数字个数
    
  • 最后结果为 n + 1 - max

###复杂度

  • 使用二分搜索可以优化至O(logn)
  • 使用STL的lower_bound缩减代码

###Code

    #include <iostream>
    #include <vector>
    #include <string>
    #include <algorithm>
    
    using namespace std;
    int DLIS2(vector<int>& a)
    {
    	int n = a.size();
    	vector<int> dp(n,INT_MAX);
    	vector<int> l(n,INT_MIN);
    	vector<int> r(n,INT_MIN);
    	//Left to right
    	for(auto i = 0; i < n; ++i)
    	{
    		auto it = lower_bound(dp.begin(),dp.begin()+n,a[i]);
    		*it = a[i];
    		l[i] = it - dp.begin() + 1;
    	}
    	//Right to left
    	fill(dp.begin(),dp.end(),INT_MAX);
    	for(auto i = n-1; i >= 0; --i)
    	{
    		auto it = lower_bound(dp.begin(),dp.begin()+n,a[i]);
    		*it = a[i];
    		r[i] = it - dp.begin() + 1;
    	}
    	int max = 0;  
        for (auto i = 0; i < n; ++i )  
    	{
            if (l[i]+r[i] > max) max = l[i] + r[i];  
    	}
    	return n+1-max;
    }
    int DLIS1(vector<int>& a)
    {
    	int i,low, high, mid, max;  
    	int n = a.size();
        vector<int>		b(n,-1);
    	vector<int>		c(n,-1);
    	vector<int>		inc(n,INT_MAX);  
          
          
        for (i = 0; i < n; ++i) 
    	{  
            low = 0; high = i;  
            while (low < high) 
    		{  
                mid = low + (high-low)*0.5;  
                if (inc[mid] < a[i])
    			{
    				low = mid + 1;  
    			}
                else 
    			{
    				high = mid;  
    			}
            }  
            b[i] = low + 1;  
            inc[low] = a[i];  
        }  
          
    	for (i = 0; i < n; ++i) 
    	{
    		inc[i] = INT_MAX;
    	}
        for (i = n-1; i >= 0; --i) 
    	{  
            low = 0; high = i;  
            while (low < high) 
    		{  
                mid = low + (high-low)*0.5;  
                if (inc[mid] < a[i])
    			{
    				low = mid + 1;  
    			}
                else 
    			{
    				high = mid; 
    			}
            }  
            c[i] = low + 1;  
            inc[low] = a[i];  
        }  
        max = 0;  
        for (i = 0; i < n; ++i )
    	{
            if (b[i]+c[i] > max) max = b[i] + c[i];  
    	}
        return n+1-max; 
    }
    int main()
    {
    	int a[20] = {1,10,2,9,3,8,4,7,5,6,6,5,7,4,8,3,9,2,10,1};
    	vector<int> test(a,a+20);
    	cout<<"(Naive DLIS)Remove "<<DLIS1(test)<<"  elements\n";
    	cout<<"(Using  STL)Remove "<<DLIS2(test)<<"  elements\n";
    	system("pause");
    	return 0;
    }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment