给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, ...)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。
示例 1:
输入: n = 12
输出: 3
解释: 12 = 4 + 4 + 4.
示例 2:
输入: n = 13
输出: 2
解释: 13 = 4 + 9.
class Solution {//动态规划 一维
public:
int numSquares(int n) {
vector<int> dp(n+1);
dp[0]=0;
dp[1]=1;
for(int i=2;i<=n;++i){
int minN=INT_MAX;
for(int j=1,temp=1;temp<=i;++j,temp=j*j){
minN=min(dp[i-temp],minN);
}
dp[i]=minN+1;
}
return dp[n];
}
};
给定一个无序的整数数组,找到其中最长上升子序列的长度。
示例:
输入: [10,9,2,5,3,7,101,18]
输出: 4
解释: 最长的上升子序列是 [2,3,7,101],它的长度是 4。
说明:
可能会有多种最长上升子序列的组合,你只需要输出对应的长度即可。
你算法的时间复杂度应该为 O(n2) 。
进阶: 你能将算法的时间复杂度降低到 O(n log n) 吗?
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
int nSize=nums.size();
if(nSize<=1)return nSize;
vector<int> dp(nSize,0);
int resMax=0,maxN;
dp[0]=1;
for(int i=1;i<nSize;++i){
maxN=0;
for(int j=0;j<i;++j)
if(nums[j]<nums[i])
maxN=max(maxN,dp[j]);
dp[i]=maxN+1;
resMax=max(dp[i],resMax);
}
//return dp[nSize-1]; //错误
return resMax;
}
};
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {//nlogn 二分查找
int nSize=nums.size();
if(nSize<=1)return nSize;
vector<int> dp(nSize+1,0);
dp[1]=nums[0];
int cur=1;//dp下标表示子序列最长长度;dp数据表示该下标/最长长度对应的末尾数字的最小值
for(int i=1;i<nSize;++i){
if(nums[i]>dp[cur])
dp[++cur]=nums[i];
else{
int le=1,ri=cur,pos=0;
while(le<=ri){//二分查找dp数据从左往右最后一个小于nums[i]的下标
int mid=le+((ri-le)>>1);
if(dp[mid]<nums[i]){
pos=mid;
le=mid+1;
}
else
ri=mid-1;
}
dp[pos+1]=nums[i];
}
}
return cur;
}
};
/*二分查找最后一个/第一个 </<= >/>=的位置
0,1,2,3,4,5,6,7,8,9
2,2,2,2,3,3,4,4,6,6*/
le=0,ri=9;
//最后一个index使得nums[index]</<=target
int pos=-1;
while(le<=ri){
int mid=(le+ri)>>1;
if(nums[mid]</<=target)
pos=mid,le=mid+1;
else ri=mid-1;
}
return pos;
//第一个index使得nums[index]>/>=target
int pos=-1;
while(le<=ri){
int mid=(le+ri)>>1;
if(nums[mid]>/>=target)
pos=mid,ri=mid-1;
else le=mid+1;
}
return pos;
给定一个二维矩阵,计算其子矩形范围内元素的总和,该子矩阵的左上角为 (row1, col1) ,右下角为 (row2, col2)。
上图子矩阵左上角 (row1, col1) = (2, 1) ,右下角(row2, col2) = (4, 3),该子矩形内元素的总和为 8。
示例:
给定 matrix = [
[3, 0, 1, 4, 2],
[5, 6, 3, 2, 1],
[1, 2, 0, 1, 5],
[4, 1, 0, 1, 7],
[1, 0, 3, 0, 5]
]
sumRegion(2, 1, 4, 3) -> 8
sumRegion(1, 1, 2, 2) -> 11
sumRegion(1, 2, 2, 4) -> 12
说明:
你可以假设矩阵不可变。
会多次调用 sumRegion 方法。
你可以假设 row1 ≤ row2 且 col1 ≤ col2。
class NumMatrix {
public:
vector<vector<int>> dp;
int mSize,nSize;
NumMatrix(vector<vector<int>>& matrix) {
mSize=matrix.size();
if(mSize){
nSize=matrix[0].size();
if(nSize){
this->dp=matrix;
for(int i=1;i<nSize;++i)
dp[0][i]+=dp[0][i-1];
for(int i=1;i<mSize;++i){
dp[i][0]+=dp[i-1][0];
for(int j=1;j<nSize;++j)
dp[i][j]=dp[i][j]+dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1];
}
}
}
}
int sumRegion(int row1, int col1, int row2, int col2) {//讨论繁琐可dp增加一行一列数据如后面所示
if(row1==0&&col1==0)return dp[row2][col2];
else if(row1==0)return dp[row2][col2]-dp[row2][col1-1];
else if(col1==0)return dp[row2][col2]-dp[row1-1][col2];
else return dp[row2][col2]+dp[row1-1][col1-1]-dp[row2][col1-1]-dp[row1-1][col2];
}
};
class NumMatrix {
private:
vector<vector<int>> prefix;
public:
NumMatrix(vector<vector<int>>& matrix) {
if(matrix.empty())return;//构造函数可return
int m=matrix.size(),n=matrix[0].size();
prefix.resize(m+1,vector<int>(n+1,0));//多一行一列
for(int i=1;i<=m;++i){
for(int j=1;j<=n;++j){
prefix[i][j]=prefix[i-1][j]+prefix[i][j-1]-prefix[i-1][j-1]+matrix[i-1][j-1];//matrix[i-1][j-1]对应prefix[i][j]
}
}
}
int sumRegion(int row1, int col1, int row2, int col2) {
if(prefix.empty())return 0;
return prefix[row2+1][col2+1]-prefix[row2+1][col1]-prefix[row1][col2+1]+prefix[row1][col1];
}
};
给定一个非负整数 num。对于 0 ≤ i ≤ num 范围中的每个数字 i ,计算其二进制数中的 1 的数目并将它们作为数组返回。
示例 1:
输入: 2
输出: [0,1,1]
示例 2:
输入: 5
输出: [0,1,1,2,1,2]
进阶:
给出时间复杂度为O(n*sizeof(integer))的解答非常容易。但你可以在线性时间O(n)内用一趟扫描做到吗?
要求算法的空间复杂度为O(n)。
你能进一步完善解法吗?要求在C++或任何其他语言中不使用任何内置函数(如 C++ 中的 __builtin_popcount)来执行此操作。
class Solution {//dp[i]=dp["去掉i最左边的1剩下的值"]+1
public:
vector<int> countBits(int num) {
vector<int> dp(num+1,0);
for(int i=1,lastD=0;i<=num;++i){
if((i&(i-1))==0)//2次幂
dp[i]=1,lastD=i;//lastD记录上一个2次幂的下标
else
dp[i]=dp[i-lastD]+1;//例如2^3<13<2^4,dp[13]=dp[13-2^3]+1;
}
return dp;
}
};
class Solution {//dp[i]=dp["去掉i最右边的1剩下的值"]+1
public:
vector<int> countBits(int num) {
vector<int> dp(num+1,0);
for(int i=1;i<=num;++i)
dp[i]=dp[i&(i-1)]+1;
return dp;
}
};
class Solution {//dp[i]=dp["去掉i第0位值剩下的值"]+dp["i第0位的值"]
public:
vector<int> countBits(int num) {
if(num==0)return vector<int>{0};
vector<int> dp(num+1,0);
dp[1]=1;
for(int i=1;i<=num;++i)
dp[i]=dp[i>>1]+dp[i%2];
return dp;
}
};