Last updated on October 14, 2024 pm
k
2024/10/13
给你一个整数数组 nums
,找到其中最长严格递增子序列的长度。
1、动态规划法
维护一个dp数组,dp[i]表示以nums[i]做结尾的最长连续递增子序列长度。
外循环遍历数组的所有元素,内循环遍历在这个元素之前的元素,如果此元素大于之前的元素,则说明可以形成一个递增子序列。于是就可以做max比较确定dp[i]的大小。
最后遍历dp数组找到最长的长度。
时间复杂度:O(n^2)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class Solution { public: int lengthOfLIS(vector<int>& nums) { int n=nums.size(); if(n==0) return 0; vector<int> dp(n,1); for(int i=0;i<n;i++){ for(int j=0;j<i;j++){ if(nums[j]<nums[i]){ dp[i]=max(dp[i],dp[j]+1); } } } return *max_element(dp.begin(),dp.end()); } };
|
2、贪心+二分查找
维护一个向量数组vec。这个数组的特点是:里面的元素保持严格递增,并且vec的长度是到nums[i]时,前面的最长递增子序列的长度。但是vec中的元素不一定是正确的子序列。
令len=1;vec[len]=nums[0];
怎么贪心呢?就是直接遍历数组,有两种情况:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| class Solution { public: int lengthOfLIS(vector<int>& nums) { int n=nums.size(),len=1; if(n==0) return 0; vector<int> vec(n+1); vec[1]=nums[0]; for(int i=1;i<n;i++){ if(nums[i]>vec[len]){ vec[++len]=nums[i]; }else{ int l=1,r=len,pos=0; while(l<=r){ int mid=(l+r)>>1; if(vec[mid]<nums[i]){ l=mid+1; } else{ pos=mid; r=mid-1; } } vec[pos]=nums[i]; } } return len; } };
|
(2)动态规划
给你一个整数数组 nums
,请你找出数组中乘积最大的非空连续 子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。测试用例的答案是一个 32-位 整数。
重点:不仅要维护最大值,还要维护最小值,因为有负数。
1 2 3 4 5 6 7 8 9 10 11 12 13
| class Solution { public: int maxProduct(vector<int>& nums) { int minF=nums[0], maxF=nums[0], n=nums.size(),ans=nums[0]; for(int i=1;i<n;i++){ int mi=minF,mx=maxF; minF=min(mi*nums[i],min(mx*nums[i],nums[i])); maxF=max(mi*nums[i],max(mx*nums[i],nums[i])); ans=max(ans,maxF); } return ans; } };
|
(3)图论
1、无向图的连通数
依次删除无向图中的点,依次返回其中的连通数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| #include "bits/stdc++.h"
using namespace std;
void dfs(unordered_map <int ,vector<int> > ball,int j,vector<bool>& num){ num[j]=true; for(int i=0;i<ball[j].size();i++){ if(num[ball[j][i]]==false) dfs(ball,ball[j][i],num); } }
int main() { int n,m; cin>>n>>m; unordered_map <int ,vector<int> > ball(n+1 while(m){ int u,v; cin>>u>>v; ball[u].push_back(v); ball[v].push_back(u); m--; } int i=1; while(i<=n){ ball[i]={}; int cnt=0; vector<bool> num(n+1,false); for(int j=i+1;j<=n;j++){ if(num[j]==false){ cnt++; dfs(ball,j,num); } } cout<<cnt<<endl; i++; } return 0; }
|
(4)数组
1、
给定一个数组,每次操作可以将相邻的两个值正负翻转,可以做无限次操作,问数组中所有元素累加起来的最大值。
这道题理清思路好简单,就是看负数是不是奇数个,如果是偶数个,就是返回所有值加在一起(也就是一定能够每个值都变成正的),如果是奇数个,那么一定会留下负数。所以直接用绝对值相加后的值减去所有数最小的绝对值*2。
1 2 3 4 5 6 7 8 9 10 11 12
| int maxSum(vector<int> nums){ int n=nums.size(); int cnt=0,mx=INT_MAX,ans=0; for(int i=0;i<n;i++){ ans+=abs(nums[i]); mi=min(mi,abs(nums[i])); if(nums[i]<0){ cnt++; } } return cnt%2==0?ans:ans-mi*2; }
|