class Solution { public: /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * 给定数组的最长严格上升子序列的长度。 * @param arr int整型vector 给定的数组 * @return int整型 */ int LIS(vector<int>& arr) { // write code here //动态规划思路一:1,状态定义:dp[i]表示以arr[i]作为结尾的LIS的长度 //2,状态转移:arr[i]显然要添加到前面已存在的LIS的末尾然后使得长度加一, //3,转移方程:dp[i]=max(dp[j])+1,其中j<i,并且arr[j]<arr[i] //4,边界条件:dp数组全部初始化为1,因为每个元素自身就是长度一的LIS //时间复杂度O(n^2),空间复杂度O(n) // int size=arr.size(); // if(size==0) // return 0; // vector<int>dp(size,1); // //遍历arr数组 // for(int i =0; i<size; i++) // { // //遍历dp数组 // for(int j=0; j<i; j++) // { // if(arr[j]<arr[i]) // dp[i]=max(dp[j]+1,dp[i]); // } // } // //algorithm中内置找最大值的函数,返回指向最大值的容器 // auto it=max_element(dp.begin(),dp.end()); // return *it; //思路二:二分查找+贪心 //1,状态定义:dp[i]代表所有长度为i+1的LIS中末位元素的最小值 //2,状态转移:初始dp为空,依次遍历arr中的元素,找到dp中第一个大于等于arr[i]的位置将其更新为arr[i],如果均小于则将dp长度加一然后把arr[i]添加到dp末尾。 //解释:dp数组必然是严格上升,可以反证法证明。每个arr[i]也只能更新dp中的一个位置,因为更新多个位置则dp中出现相同元素就不满足严格上升。在我们遍历到arr[i]时,理论上它可以更新dp中第一个大于等于arr[i]以及之前的所有位置,但要满足dp是最小末尾的条件我们只能更新最后一个位置。 vector<int>dp; int size=arr.size(); //遍历arr for(int i=0; i<size; i++) { //找到dp中第一个大于等于arr[i]的位置(lower_bound找到第一个大于等于的位置,upper_bound找到第一个大于的位置) auto it =lower_bound(dp.begin(),dp.end(),arr[i]); //如果找到 if(it!=dp.end()) *it=arr[i]; //没找到 else { dp.push_back(arr[i]); } } //最后返回dp数组的长度即可 return dp.size(); } };