@LIUHUAN
2019-12-29T17:41:34.000000Z
字数 14570
阅读 1622
algorithm
int findLengthOfLCIS(vector<int>& nums) {
int n = nums.size();
if(n <= 1)
return n;
int maxlen = 1;
for(int i = 0; i < n;i++ ) {
int len = 1;// 每次nums[i] 开始的序列最大长度为1,往后增长
for(int j = i+ 1;j < n;j++){
if(nums[j] > nums[j-1] ) {// 连续递增
len += 1; // 长度增加
maxlen = max(maxlen,len);
}else {// 不连续递增了,下一个元素继续计算
break;
}
}
return maxlen;
}
int findLengthOfLCIS(vector<int>& nums) {
int n = nums.size();
if(n <= 1)
return n;
vector<int> dp(n,1);
int maxlen = 1;
for(int i = 1; i < n; i++ ) {
if( nums[i] > nums[i-1] ) {
dp[i] = dp[i-1] + 1 ;
}
maxlen = max( dp[i] , maxlen );
}
return maxlen;
}
int lengthOfLIS(vector<int>& nums) {
int n = nums.size();
if(n <= 1 )
return n;
vector<int> dp(n,1);// 初始化为1
int max_len = 1;
for(int i = 1 ;i < n; i++) {
for(int j = i-1 ;j >=0 ;j-- ) { // 遍历[0,i-1]的元素加上nums[i] 之后的长度是否构成更长的递增子序列
if(nums[j] < nums[i]) {
dp[i] = max(dp[i],dp[j] + 1 );
max_len = max(max_len,dp[i]);
}
}
}
return max_len;
}
int findNumberOfLIS(vector<int>& nums) {
int n = nums.size();
if(n <= 1)
return n;
vector<int> dp(n,1); // nums[i]结尾的最长递增子序列长度
int max_len = 1;//最大长度
vector<int> max_c(n,1);// 每个最长子序列的长度默认为1
for(int i = 1; i < n; i++ ){
for(int j = i - 1; j >= 0; j-- ) {
if(nums[i] > nums[j]) {
if(dp[i] < dp[j] + 1){// dp[i] 可以从dp[j] 扩展得到更长的子序列,那么最长子序列的个数就是扩展前dp[j]的个数,max_c[j]
max_c[i] = max_c[j]; // 扩展后的来源个数
}else if(dp[i] == dp[j] + 1) { // 相同长度的其他扩展而来的子序列
max_c[i] += max_c[j] ; // 因为长度相同,所以求和来源的个数
}
dp[i] = max(dp[i],dp[j] + 1);
max_len = max(dp[i],max_len);
}
}
}
// 遍历所有的dp[i]等于最大长度时,求和所有的max_c[i],得到最大长度递增子序列的个数和
int maxc = 0;
for(int i = 0; i < n ; i++) {
if(dp[i] == max_len) {
maxc += max_c[i];
}
}
return maxc;
}
int findLongestChain(vector<vector<int>>& pairs) {
int n = pairs.size();
if(n <= 1)
return n;
sort(pairs.begin(),pairs.end(),[](vector<int>& a,vector<int>&b ){return a[0] < b[0];});
vector<int> dp(n,1);
int max_len = 1;
for(int i =1;i < n; i++) {
int ifirst = pairs[i][0];
for(int j =i -1 ;j >= 0; j--) {
if(pairs[j][1] < ifirst) { // 构成递增链
dp[i] = max(dp[i],dp[j] + 1); //更新递增链大小
max_len = max(max_len,dp[i]);
}
}
}
return max_len;
}
int numberOfArithmeticSlices(vector<int>& A) {
int n = A.size();
if(n <= 2 )
return 0;
vector<vector<int> > dp(n,vector<int>(n,0));
for(int i = 1; i < n-1; i++) {
dp[i-1][i+1] = (A[i] -A[i-1] == A[i+1] -A[i] );
}
for(int k = 3; k < n ;k++ ) {
for(int i = 0; i < n; i++ ) {
int j = i + k;
if(j >= n)
break;
dp[i][j] = dp[i][j-1] && (A[j] - A[j-1] == A[j-1] - A[j-2]);
}
}
int c = 0;
for(int i =0 ;i < n; i++) {
for(int j = i+2;j < n; j++) {
if(dp[i][j] == 1)
c += 1;
}
}
return c;
}
int longestArithSeqLength(vector<int>& A) {
int n = A.size();
vector<vector<int>> dp(n,vector<int>(n,2));
for(int i = 0; i < n; i++ ) {
dp[i][i] = 0;
}
int maxlen = 2;
for(int i = 1; i < n; i++ ) {
for(int j = i + 1; j <n ; j++) {
int ak = 2*A[i] - A[j]; // 查找A[j] - A[i] == A[i] - A[k]
for(int k = 0; k < i ;k++) {
if(A[k] == ak) {
dp[i][j] = max(dp[i][j] , dp[k][i] + 1 );
maxlen = max(dp[i][j],maxlen);
}
}
}
}
return maxlen;
}
int numberOfArithmeticSlices(vector<int>& A) {
int n = A.size();
vector<vector<int>> dp(n,vector<int>(n,0));
int sum = 0;
for(int i = 0; i < n; i++ ) {
for(int j = i + 1; j < n; j++ ) {
// int ak = 2*A[i] - A[j]; // mind overflow !!!
long t = A[j];
t -= A[i];
for(int k = 0; k < i; k++ ) {
long x = A[i];
x -= A[k];
if(t == x ) {
dp[i][j] += dp[k][i] + 1;
}
}
sum += dp[i][j];
}
}
return sum;
}
int getMoneyAmount(int n) {
vector<vector<int>> dp(n+1,vector<int>(n+1,INT_MAX));// 默认最大代价
for(int i = 1;i < n ; i++) {
dp[i][i+1] = i; // 初始情况步长为1
dp[i][i] = 0;
}
dp[0][0] = 0;
dp[n][n] = 0;
int k = 2;// 步长为2
for(int k =2 ;k <= n; k++ ) {
for(int i = 1;i <= n; i++) {
int j = i + k;// [i,j]范围内
if(j > n)
break;
int mincost = INT_MAX;
for(int m = i+1; m < j;m++) { // [i,m-1],[m+1,j]
int t = max(dp[i][m-1],dp[m+1][j]) + m; // 选择猜测m,之后的最保险策略(能够猜到候选数的最大代价,付出这个代价,无论第二步,第三步,怎么猜测,一定能够找到候选数)
mincost = min(mincost,t); // 选择一个最小,最为[i,j]的猜测代价
}
dp[i][j] = mincost;
}
}
return dp[1][n]; // 返回[1,n]最小代价
}
bool PredictTheWinner(vector<int>& nums) {
int n = nums.size();
vector<vector<int>> dp(n,vector<int>(n,0));
int sum = 0;
for( int i = 0; i < n; i++ ) {
dp[i][i] = nums[i];
sum += nums[i];
}
for( int k = 1; k < n; k++ ) {
for( int i = 0; i < n; i++ ) {
int j = i + k ;
if(j >= n )
break;
int ni = min(getij (dp,i+1,j-1),getij(dp,i+2,j)) + nums[i];
int nj = min(getij(dp,i+1,j-1),getij(dp,i,j-2)) + nums[j];
dp[i][j] = max( ni ,nj );
}
}
return dp[0][n-1] >= sum - dp[0][n-1];
}
int getij(vector<vector<int>>& dp,int i,int j) {
int n = dp.size();
if( i >= n || j >= n || i < 0 || j < 0 || i > j )
return 0;
return dp[i][j];
}
bool stoneGame(vector<int>& piles) {
int m = piles.size();
// int n = piles[0].size();
vector<vector<int>> dp(m,vector<int>(m,0));
int sum = 0;
for(int i = 0 ;i < m ;i++) {
sum += piles[i];
}
for(int k = 1; k < m ;k+=2) {
for(int i = 0 ;i < m;i++) {
int j = i + k ;
if(j >= m)
break;
int front = piles[i] + max(getij(dp,i+1,j-1),getij(dp,i+2,j) );
int end = piles[j] + max(getij(dp,i,j-2) , getij(dp,i+1,j-1) );
dp[i][j] = max(front,end);
}
}
return sum - dp[0][m-1] < dp[0][m-1];
}
int getij(vector<vector<int>>& dp,int i ,int j){
int m = dp.size();
if(i < 0 || j >= m || i >= m || j < 0)
return 0;
return dp[i][j];
}
int numSquares(int n) {
if(n <= 0)
return 0;
if(n == 1)
return 1;
vector<int> dp(n+1,0);
dp[1] = 1;
for(int i = 2;i <= n; i++ ) {
int m = int(sqrt(i)); // 不会超过这
int t = INT_MAX;
for(int k = 1 ;k <= m;k++){ // 从1开始遍历
int j = k * k;
t = min(dp[i-j] +1 ,t);//最小值
}
dp[i] = t;
}
return dp[n];
}
// n^3
int lenLongestFibSubseq(vector<int>& A) {
int n = A.size();
vector<vector<int>> dp(n,vector<int>(n,2));// 除自己与自己外,所有的序列长度默认为2
int maxlen = 0;
for(int i = 0; i < n; i++ ) {
dp[i][i] = 0; // 自己与自己构成的序列长度设置为0
for(int j = i + 1; j< n; j++ ) { // (A[i],A[j])
for(int k = 0; k < i; k++ ) { // 对k执行搜索,0<= k < i
if(A[i] + A[k] == A[j]) { // A[j] 与(A[k],A[i])可以构成更长的序列
dp[i][j] = max(dp[i][j],dp[k][i] + 1);
maxlen = max(maxlen,dp[i][j]);
}
}
}
}
return maxlen;
}
lower_bound
函数,可以在返回值中判断是否存在
int lenLongestFibSubseq(vector<int>& A) {
int n = A.size();
vector<vector<int>> dp(n,vector<int>(n,2));
int t,maxlen = 0;
for(int i = 0;i < n; i++) {
dp[i][i] = 0;
for(int j = i+1; j< n; j++) {
int ak = A[j] - A[i];
auto loc = lower_bound(A.begin(),A.begin() + i,ak); // 查找A[k]
if(*loc == ak) {
int k = loc - A.begin();
dp[i][j] = max(dp[i][j],dp[k][i] + 1);
maxlen = max(maxlen,dp[i][j]);
}
}
}
return maxlen;
}
int lenLongestFibSubseq(vector<int>& A) {
int n = A.size();
vector<vector<int>> dp(n,vector<int>(n,2));
int t,maxlen = 0;
unordered_map<int,int> umap;
for(int i = 0; i < n; i++ ) {
umap[A[i]] = i; // 存储所有的值与下标
dp[i][i] = 0;
}
for(int i = 0;i < n; i++) {
for(int j = i + 1; j< n; j++) {
int ak = A[j] - A[i];
auto e = umap.find(ak); // 查找A[k]
if(e != umap.end() && e->second < i ) { // be careful the e->second < i
int k = e->second;
dp[i][j] = max(dp[i][j], dp[k][i] + 1);
maxlen = max(maxlen, dp[i][j]);
}
}
}
return maxlen;
}
int wiggleMaxLength(vector<int>& nums) {
int n = nums.size();
if(n <= 0)
return 0;
vector<vector<int>> dp(n,vector<int>());
for(int i = 0 ;i < n; i++ ) {
dp[i] = {1,1};
}
int maxlen = 1;
for( int i = 1; i < n; i++ ) {
for( int j = i - 1; j >=0; j-- ) {
if(nums[j] > nums[i]) { // 构成上摆数组
dp[i][1] = max(dp[i][1] ,dp[j][0] + 1);
}else if( nums[j] < nums[i] ) { // 构成下摆数组
dp[i][0] = max(dp[i][0] ,dp[j][1] + 1);
}
maxlen = max(maxlen,dp[i][0]);
maxlen = max(maxlen,dp[i][1]);
}
}
return maxlen;
}
int maxProduct(vector<int>& nums) {
int n = nums.size();
vector<vector<int>> dp(n,vector<int>());
if( n <=0 )
return 0;
for(int i = 0; i < n; i++ ) {
dp[i] = {nums[i],nums[i]};
}
int maxv = nums[0];
for(int i = 1; i < n; i++ ) {
int a = nums[i];
if( a < 0) {
dp[i][0] = max(dp[i-1][1] * a ,a);
dp[i][1] = min(dp[i-1][0] * a, a);
}else if( a > 0) {
dp[i][0] = max(dp[i-1][0] * a, a);
dp[i][1] = min(dp[i-1][1] * a, a);
}
maxv = max(maxv,dp[i][0]);
}
return maxv;
}