1、两数之和
使用unoredred_map进行存储,注意!map的申请形式是<int,int>
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
int n=nums.size();
unordered_map<int,int> map1;
for(int i=0;i<n;i++){
int x=target-nums[i];
if(map1.find(x)!=map1.end()){
return {map1[x],i};
}
else map1[nums[i]]=i;
}
return {-1,-1};
}
};
2:两数相加
使用a记录进位,每次循环一定要将求和ans置零!!最后一定要加判断,是否最后a是1,如果是1,需要再加一个链表结点记录最高位!!
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
if(l1==NULL) return l2;
if(l2==NULL) return l1;
ListNode* result=new ListNode(0);
ListNode* re=result;
int ans=0,a=0;
while(l1!=NULL||l2!=NULL){
ans=0;
if(l1!=NULL){
ans+=l1->val;
l1=l1->next;
}
if(l2!=NULL){
ans+=l2->val;
l2=l2->next;
}
ans+=a;
a=ans/10==0?0:1;
re->next=new ListNode(ans%10);
re=re->next;
}
if(a==1) re->next=new ListNode(a);
return result->next;
}
};
3:无重复字符的最长子串(再刷)
这个题的关键!!使用双指针,left到right所有字符与right判断,如果没有相等的,一步步右移right,有相等的,移动left指针。全程使用len记录当前长度。
注意:每更新一次left,需要重新设置len!!!
class Solution {
public:
int lengthOfLongestSubstring(string s) {
if(s.size()==0) return 0;
int m=s.size();
int len=0,re=0;
int left=0,right=0;
while(right<m){
for(int i=left;i<right;i++){
if(s[i]==s[right]){
left=i+1;
len=right-left;
}
}
right++;
len++;
re=max(re,len);
}
return re;
}
};
5:最长回文子串(再刷)
使用动态规划,但是需要注意:判断要使用==,而且substr用法,s.substr(开始截取位置坐标,截取长度)
class Solution {
public:
string longestPalindrome(string s) {
if(s.size()==0) return s;
int m=s.size();
vector<vector<int>> dp(m,vector<int>(m));
int start=0,len=0;
for(int i=0;i<s.size();i++){
dp[i][i]=1;
len=1;
}
for(int j=0;j<m-1;j++){
if(s[j]==s[j+1]){
dp[j][j+1]=1;
len=2;
start=j;
}
}
for(int l=3;l<=m;l++){
for(int i=0;i<=m-l;i++){
int j=i+l-1;
if(s[i]==s[j]&&dp[i+1][j-1]==1){
dp[i][j]=1;
len=l;
start=i;
}
}
}
return s.substr(start,len);
}
};
7:整数反转
使用vector容器存储,判断是否超过存储大小!
class Solution {
public:
int reverse(int x) {
if(x==0) return x;
vector<int> re;
while(x){
re.push_back(x%10);
x=x/10;
}
long ans=0;
for(int i=0;i<re.size();i++){
ans=ans*10+re[i];
if(ans>INT_MAX||ans<INT_MIN)
return 0;
}
return ans;
}
};
9:回文数
使用vector存储,记录错误:x.size(),应该是re.size()。仔细检查!!!re[right]不是right
class Solution {
public:
bool isPalindrome(int x) {
if(x==0) return true;
vector<int> re;
if(x<0) return false;
while(x){
re.push_back(x%10);
x=x/10;
}
int left=0,right=re.size()-1;
while(left<right){
if(re[left]!=re[right]) {
return false;
}
left++;
right--;
}
return true;
}
};
11:盛最多水的容器
使用双指针!左指针小,那么所有以左指针为边界的组合都小于当前情况,因为左指针固定最低高度,而宽度减少。
class Solution {
public:
int maxArea(vector<int>& height) {
int m=height.size();
if(m==0) return 0;
int left=0,right=m-1;
int ans=0,len=0;
while(left<right){
len=min(height[left],height[right])*(right-left);
ans=max(ans,len);
if(height[left]<height[right]) left++;
else if(height[left]>=height[right]) right--;
}
return ans;
}
};
14:最长公共前缀
想清楚,最长公共前缀,只要有不符合直接退出,输出前缀
class Solution {
public:
string longestCommonPrefix(vector<string>& strs) {
if(strs.size()==0) return "";
if(strs[0].size()==0) return "";
int m=strs[0].size();
int n=strs.size();
int a=0;
string ans;
for(int i=0;i<m;i++){
for(int j=1;j<n;j++){
if(strs[0][i]!=strs[j][i]){
a=1;
}
}
if(a==0) ans+=strs[0][i];
if(a==1) return ans;
}
return ans;
}
};
15:三数之和(再刷一遍!)
再刷一遍!注意双指针用法以及去重,同时注意while判断
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> result;
int m=nums.size();
if(m==0) return result;
sort(nums.begin(),nums.end());
for(int i=0;i<m;i++){
if(nums[i]>0) return result;
if(i>0&&nums[i]==nums[i-1]) continue;
int left=i+1,right=m-1;
while(left<right){
if(nums[i]+nums[left]+nums[right]>0) right--;
else if(nums[i]+nums[left]+nums[right]<0) left++;
else{
result.push_back(vector<int>{nums[i],nums[left],nums[right]});
while(left<right&&nums[left]==nums[left+1]) left++;
while(left<right&&nums[right]==nums[right-1]) right--;
left++;
right--;
}
}
}
return result;
}
};
16:最接近的三数之和
还是使用双指针法进行判断,需要制定一个判断距离的变量
class Solution {
public:
int threeSumClosest(vector<int>& nums, int target) {
int m=nums.size();
sort(nums.begin(),nums.end());
if(m==0) return 0;
int len=INT_MAX,ans=0;
for(int i=0;i<m;i++){
int left=i+1,right=m-1;
while(left<right){
if(nums[i]+nums[left]+nums[right]==target) return target;
int x=nums[i]+nums[left]+nums[right];
if(abs(x-target)<len) {
len=abs(x-target);
ans=x;
}
if(x>target) right--;
else if(x<target) left++;
}
}
return ans;
}
};
17:电话号码的字母组合
class Solution {
public:
string path;
vector<string> result;
string letter[10]={"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
void travel(string digits,int index){
if(index==digits.size()) {
result.push_back(path);
return;
}
int digit=digits[index]-'0';
string letters=letter[digit];
for(int i=0;i<letters.size();i++){
path.push_back(letters[i]);
travel(digits,index+1);
path.pop_back();
}
}
vector<string> letterCombinations(string digits) {
int m=digits.size();
if(m==0) return result;
travel(digits,0);
return result;
}
};
18:四数之和
使用双指针,同样必须关注括号类型,i–与i-1不同!
注意!!!left和right指针也需要循环,因此也需要使用while(left<right)判断
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
int m=nums.size();
sort(nums.begin(),nums.end());
vector<vector<int>> result;
if(m==0) return result;
for(int i=0;i<m;i++){
if(i>0&&nums[i]==nums[i-1]) continue;
for(int j=i+1;j<m;j++){
if(j>i+1&&nums[j]==nums[j-1]) continue;
int left=j+1,right=m-1;
while(left<right){
int x=nums[i]+nums[j]+nums[left]+nums[right];
if(x<target) left++;
else if(x>target) right--;
else{
result.push_back(vector<int>{nums[i],nums[j],nums[left],nums[right]});
while(left<right&&nums[left]==nums[left+1]) left++;
while(left<right&&nums[right]==nums[right-1]) right--;
left++;
right--;
}
}
}
}
return result;
}
};
19:删除链表的倒数第N个结点
使用双指针
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* dummy=new ListNode(0);
dummy->next=head;
ListNode* right=head;
for(int i=0;i<n;i++){
right=right->next;
}
ListNode* left=dummy;
while(right!=NULL){
left=left->next;
right=right->next;
}
left->next=left->next->next;
return dummy->next;
}
};
20:有效的括号
注意栈是push,不是push_back!!!
class Solution {
public:
bool isValid(string s) {
int m=s.size();
if(m==0) return true;
stack<int> re;
for(int i=0;i<m;i++){
if(s[i]=='(') re.push(')');
else if(s[i]=='{') re.push('}');
else if(s[i]=='[') re.push(']');
else if(!re.empty()&&s[i]==re.top()) re.pop();
else if(re.empty()||s[i]!=re.top()) return false;
}
if(!re.empty()) return false;
else return true;
}
};
21:合并两个有序链表
一定要加else!!!不然l1->next会判断出界
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
if(l1==NULL) return l2;
if(l2==NULL) return l1;
ListNode* result=new ListNode(0);
ListNode* re=result;
while(l1!=NULL||l2!=NULL){
if(l1==NULL){
re->next=l2;
l2=l2->next;
}
else if(l2==NULL){
re->next=l1;
l1=l1->next;
}
else if(l1->val<l2->val){
re->next=l1;
l1=l1->next;
}
else if(l1->val>=l2->val){
re->next=l2;
l2=l2->next;
}
re=re->next;
}
return result->next;
}
};
22:括号生成
使用回溯法!!!
认真,主函数变量名与子函数变量名不同!!!
left是左括号数量,right是右括号数量。注意不能使用引用,只在子函数里面处理输出就行
class Solution {
public:
void travel(vector<string>& ans,string a,int left,int right,int max){
if(a.size()==2*max) {
ans.push_back(a);
return;
}
if(left<max) travel(ans,a+'(',left+1,right,max);
if(left>right&&right<max) travel(ans,a+')',left,right+1,max);
}
vector<string> generateParenthesis(int n) {
vector<string> result;
if(n==0) return result;
travel(result,"",0,0,n);
return result;
}
};
24:两两交换链表中的结点
在一个循环中定义指针,想清楚每一步返回什么(返回交换后的第一个结点!!)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
if(head==NULL||head->next==NULL) return head;
ListNode* cur=head->next;
head->next=swapPairs(cur->next);
cur->next=head;
return cur;
}
};
26:删除排序数组中的重复项
使用双指针法,nums[j]与nums[i]不断比较
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
int m=nums.size();
if(m==0) return 0;
int i=0,j=0;
for(int j=0;j<m;j++){
if(nums[i]!=nums[j]){
nums[i+1]=nums[j];
i++;
}
}
return i+1;
}
};
31:下一个排列
本质上是将大的数字移到前面,但是由于必须按照顺序改变,因此尽量每次增大的最小。因此从后往前找到递增的nums[i],再找到nums[i]后最靠后的比他大的数,将两者交换,注意!同时需要将i后面排序。本质:升序变成降序!!!
class Solution {
public:
void nextPermutation(vector<int>& nums) {
int m=nums.size();
if(m==0||m==1) return;
int i=m-2;
while(i>=0&&nums[i]>=nums[i+1]) i--;
if(i>=0){
int j=m-1;
while(j>i&&nums[i]>=nums[j]) j--;
swap(nums[i],nums[j]);
}
sort(nums.begin()+i+1,nums.end());
}
};
33:搜索旋转排序数组
一定有一半是有序数组,二分法分两种情况讨论
左闭右闭区间
class Solution {
public:
int search(vector<int>& nums, int target) {
int m=nums.size();
if(m==0) return -1;
if(m==1) return nums[0]==target?0:-1;
int left=0;
int right=m-1;
while(left<=right){
int mid=left+(right-left)/2;
if(nums[mid]==target) return mid;
if(nums[mid]>=nums[left]){
if(nums[left]<=target&&nums[mid]>target) right=mid-1;
else left=mid+1;
}
else{
if(nums[mid]<target&&nums[right]>=target) left=mid+1;
else right=mid-1;
}
}
return -1;
}
};
34:在排序数组中查找元素的第一个和最后一个位置
使用双指针法,但是一定要确定指针不能越界,比如加上i>=0
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
int m=nums.size();
if(m==0) return {-1,-1};
int left=0,right=m-1,ans=-1;
while(left<=right){
int mid=left+(right-left)/2;
if(nums[mid]==target) {
ans=mid;
break;
}
if(nums[mid]<target) left=mid+1;
else right=mid-1;
}
if(ans==-1) return {-1,-1};
int i=ans;
while(i>=0&&nums[i]==target) i--;
int j=ans;
while(j<m&&nums[j]==target) j++;
return {i+1,j-1};
}
};
35:搜索插入位置
双指针法,注意最后是right+1
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int m=nums.size();
if(m==0) return 0;
int left=0,right=m-1;
while(left<=right){
int mid=left+(right-left)/2;
if(nums[mid]==target) return mid;
if(nums[mid]<target) left=mid+1;
if(nums[mid]>target) right=mid-1;
}
return right+1;
}
};
38:外观数列(再刷一遍)
其实原理很简单,不要怕想,就是使用递归!!!一定要注意,每次其实需要i++
class Solution {
public:
string countAndSay(int n) {
if(n==1) return "1";
string pre=countAndSay(n-1),ans;
for(int i=0;i<pre.size();i++){
int j=i;
while(j<pre.size()&&pre[j]==pre[i]) j++;
ans+=to_string(j-i);
ans+=pre[i];
i=j-1;
}
return ans;
}
};
或者固定i,让j变化与i比较。注意j需要从与i相等的地方开始比较,否则无法遍历单数。最后一个数字需要比较,因此j要等于长度也可以
class Solution {
public:
string countAndSay(int n) {
if(n==1) return "1";
string pre=countAndSay(n-1),ans;
int i=0;
for(int j=0;j<=pre.size();j++){
if(pre[j]==pre[i]) continue;
ans+=to_string(j-i);
ans+=pre[i];
i=j;
j--;
}
return ans;
}
};
39:组合总和
使用回溯!注意对于一个集合求组合,需要使用index,避免重复
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void travel(vector<int> candidates,int ans,int index){
if(ans==0) {
result.push_back(path);
return;
}
if(ans<0) return;
for(int i=index;i<candidates.size();i++){
path.push_back(candidates[i]);
travel(candidates,ans-candidates[i],i);
path.pop_back();
}
}
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
int m=candidates.size();
if(m==0) return result;
travel(candidates,target,0);
return result;
}
};
进行剪枝,排序后可以直接判断需不需要进入下一递归
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void travel(vector<int> candidates,int ans,int index){
if(ans==0) {
result.push_back(path);
return;
}
if(ans<0) return;
for(int i=index;i<candidates.size()&&ans-candidates[i]>=0;i++){
path.push_back(candidates[i]);
travel(candidates,ans-candidates[i],i);
path.pop_back();
}
}
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
int m=candidates.size();
if(m==0) return result;
sort(candidates.begin(),candidates.end());
travel(candidates,target,0);
return result;
}
};
40:组合总和2
使用回溯,注意去重操作!同一层不能同时使用两次
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void travel(vector<int> candidates,int ans,int index){
if(ans==0) {
result.push_back(path);
return;
}
if(ans<0) return;
for(int i=index;i<candidates.size()&&ans-candidates[i]>=0;i++){
if(i>index&&candidates[i]==candidates[i-1]) continue;
path.push_back(candidates[i]);
travel(candidates,ans-candidates[i],i+1);
path.pop_back();
}
}
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
int m=candidates.size();
if(m==0) return result;
sort(candidates.begin(),candidates.end());
travel(candidates,target,0);
return result;
}
};
46:全排列
排列问题需要使用use数组,记录使用次数,同时需要从0开始
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void travel(vector<int>nums,vector<bool>& used){
if(path.size()==nums.size()){
result.push_back(path);
return;
}
for(int i=0;i<nums.size();i++){
if(used[i]==false) continue;
path.push_back(nums[i]);
used[i]=false;
travel(nums,used);
used[i]=true;
path.pop_back();
}
}
vector<vector<int>> permute(vector<int>& nums) {
int m=nums.size();
if(m==0) return result;
vector<bool> used(nums.size(),true);
travel(nums,used);
return result;
}
};
48:旋转图像
自外向内一共有不超过 n/2n/2 层,从外而内顺时针循环!使用for循环
i是层数,j是上下边界,下边界为m-i-1。其中j需要小于m-1-2*i
class Solution {
public:
void rotate(vector<vector<int>>& matrix) {
if(matrix.size()==0||matrix[0].size()==0) return;
int m=matrix.size();
int s=0;
for(int i=0;m-2*i>1;i++){ //或者i<m/2
for(int j=0;j<m-1-2*i;j++){ //或者j<n+1/2
int s=matrix[i][i+j];
matrix[i][i+j]=matrix[m-1-i-j][i];
matrix[m-1-i-j][i]=matrix[m-1-i][m-1-i-j];
matrix[m-1-i][m-1-i-j]=matrix[i+j][m-1-i];
matrix[i+j][m-1-i]=s;
}
}
}
};
后续加入直接翻转
class Solution {
public:
void rotate(vector<vector<int>>& matrix) {
int n = matrix.size();
// 水平翻转
for (int i = 0; i < n / 2; ++i) {
for (int j = 0; j < n; ++j) {
swap(matrix[i][j], matrix[n - i - 1][j]);
}
}
// 主对角线翻转
for (int i = 0; i < n; ++i) {
for (int j = 0; j < i; ++j) {
swap(matrix[i][j], matrix[j][i]);
}
}
}
};
49:字母异位词分组
分类题,使用哈希表,第一遍分好类,第二遍取出即可。关键是如何分类,key值怎么取!
注意变量对应
class Solution {
public:
vector<vector<string>> groupAnagrams(vector<string>& strs) {
vector<vector<string>> result;
if(strs.size()==0) return result;
unordered_map<string,vector<string>> ans;
for(int i=0;i<strs.size();i++){
string s=strs[i];
sort(s.begin(),s.end());
ans[s].push_back(strs[i]);
}
for(auto l:ans){
result.push_back(l.second);
}
return result;
}
};
50:pow(x,n)
使用递归,考虑负号!!!本题有几个坑,首先r=i*n报错,必须使用long long型,输入负数转为正数会溢出。直接给long long赋值-2147483648会出错,问题不清楚!!!
class Solution {
public:
double myPow1(double x, long long n) {
if(n==1) return x;
int w=n%2;
double s=myPow(x,n/2);
if(w==1) return s*s*x;
else return s*s;
}
double myPow(double x, int n) {
if(n==0) return 1;
int i=1;
if(n<0) i=-1;
long long r=n;
double s=myPow1(x,r*i);
if(n<0) return 1/s;
else return s;
}
};
53:最大子序和
使用动态规划,注意max1开始取值,避免只有一个数的情况
class Solution {
public:
int maxSubArray(vector<int>& nums) {
if(nums.size()==0) return 0;
vector<int> dp(nums.size());
dp[0]=nums[0];
int max1=nums[0];
for(int i=1;i<nums.size();i++){
dp[i]=max(dp[i-1]+nums[i],nums[i]);
max1=max(max1,dp[i]);
}
return max1;
}
};
54:螺旋矩阵(再刷)
参考题解中大神答案:
1、首先设定上下左右边界
2、其次向右移动到最右,此时第一行因为已经使用过了,可以将其从图中删去,体现在代码中就是重新定义上边界
3、判断若重新定义后,上下边界交错,表明螺旋矩阵遍历结束,跳出循环,返回答案
4、若上下边界不交错,则遍历还未结束,接着向下向左向上移动,操作过程与第一,二步同理
5、不断循环以上步骤,直到某两条边界交错,跳出循环,返回答案
class Solution {
public:
vector<int> spiralOrder(vector<vector<int>>& matrix) {
vector<int> ans;
int up=0,down=matrix.size()-1;
int le=0,ri=matrix[0].size()-1;
while(true){
for(int j=le;j<=ri;j++) ans.push_back(matrix[up][j]);
if(++up>down) break;
for(int i=up;i<=down;i++) ans.push_back(matrix[i][ri]);
if(--ri<le) break;
for(int j=ri;j>=le;j--) ans.push_back(matrix[down][j]);
if(--down<up) break;
for(int i=down;i>=up;i--) ans.push_back(matrix[i][le]);
if(++le>ri) break;
}
return ans;
}
};
55:跳跃游戏
每次取最大跳跃步数(取最大覆盖范围),整体最优解:最后得到整体最大覆盖范围,看是否能到终点。关键是cover是一个整体变量,能多远到达。注意:必须要小于等于cover,能最远到达的位置
class Solution {
public:
bool canJump(vector<int>& nums) {
int cover=0;
if(nums.size()==1) return true;
for(int i=0;i<=cover;i++){
cover=max(i+nums[i],cover);
if(cover>=nums.size()-1) return true;
}
return false;
}
};
45:跳跃游戏2
从覆盖范围出发,不管怎么跳,覆盖范围内一定是可以跳到的,以最小的步数增加覆盖范围,覆盖范围一旦覆盖了终点,得到的就是最小步数!
注意!一定要理解步数增加的条件,就是到了当前能跳到最大距离,但是没到最后,不论下一个最大距离是哪一步得到的,只要能跳到,加一就行
class Solution {
public:
int jump(vector<int>& nums) {
if (nums.size() == 1) return 0;
int curDistance = 0; // 当前覆盖最远距离下标
int ans = 0; // 记录走的最大步数
int nextDistance = 0; // 下一步覆盖最远距离下标
for (int i = 0; i < nums.size(); i++) {
nextDistance = max(nums[i] + i, nextDistance); // 更新下一步覆盖最远距离下标
if (i == curDistance) { // 遇到当前覆盖最远距离下标
if (curDistance != nums.size() - 1) { // 如果当前覆盖最远距离下标不是终点
ans++; // 需要走下一步
curDistance = nextDistance; // 更新当前覆盖最远距离下标(相当于加油了)
if (nextDistance >= nums.size() - 1) break; // 下一步的覆盖范围已经可以达到终点,结束循环
} else break; // 当前覆盖最远距离下标是集合终点,不用做ans++操作了,直接结束
}
}
return ans;
}
};
56:合并区间
排序加双指针,关键在于判断左边第二个元素与右边第一个元素的大小
class Solution {
public:
vector<vector<int>> merge(vector<vector<int>>& intervals) {
int m=intervals.size();
vector<vector<int>> ans;
vector<int> s;
sort(intervals.begin(),intervals.end());
if(m==0) return ans;
int j,l;
for(int i=0;i<m;){
j=i+1;;
l=intervals[i][1];
while(j<intervals.size()&&intervals[j][0]<=l){
l=max(l,intervals[j][1]);
j++;
}
ans.push_back(vector<int>{intervals[i][0],l});
i=j;
}
return ans;
}
};
61:旋转链表
各种特殊情况!!!k不一定小于size()
快慢指针
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* rotateRight(ListNode* head, int k) {
if(head==NULL||head->next==NULL) return head;
if(k==0) return head;
ListNode* l1=head;
int c=0;
for(int i=0;i<k;i++){
l1=l1->next;
c++;
if(l1==NULL) {
l1=head;
k=c+k%c;
}
}
ListNode* l2=head;
while(l1->next){
l1=l1->next;
l2=l2->next;
}
l1->next=head;
ListNode* cur=new ListNode(0);
cur->next=l2->next;
l2->next=NULL;
return cur->next;
}
};
62:不同路径
动态规划
class Solution {
public:
int uniquePaths(int m, int n) {
if(m==0||n==0) return 0;
vector<vector<int>> dp(m,vector<int>(n));
for(int i=0;i<m;i++) dp[i][0]=1;
for(int i=0;i<n;i++) dp[0][i]=1;
for(int j=1;j<n;j++){
for(int i=1;i<m;i++){
dp[i][j]=dp[i-1][j]+dp[i][j-1];
}
}
return dp[m-1][n-1];
}
};
64:最小路径和
动态规划,注意!!!一定要返回m-1,n-1
class Solution {
public:
int minPathSum(vector<vector<int>>& grid) {
int m=grid.size(),n=grid[0].size();
if(m==0||n==0) return -1;
vector<vector<int>> dp(m,vector<int>(n));
dp[0][0]=grid[0][0];
for(int i=1;i<m;i++) dp[i][0]=dp[i-1][0]+grid[i][0];
for(int i=1;i<n;i++) dp[0][i]=dp[0][i-1]+grid[0][i];
for(int i=1;i<m;i++){
for(int j=1;j<n;j++){
dp[i][j]=min(dp[i-1][j]+grid[i][j],dp[i][j-1]+grid[i][j]);
}
}
return dp[m-1][n-1];
}
};
66:加一
逻辑很简单,但是需要想清楚,就是对每一位判断是否等于9
class Solution {
public:
vector<int> plusOne(vector<int>& digits) {
int a=0;
if(digits[digits.size()-1]<9) {
digits[digits.size()-1]++;
return digits;
}
else {
for(int i=digits.size()-1;i>=0;i--){
if(digits[i]==9) {
digits[i]=0;
}
else {
digits[i]++;
return digits;
}
}
vector<int> result(digits.size()+1);
result[0]=1;
return result;
}
}
};
69:x的平方根
二分查找
注意类型,可能x值比较大,那么最开始迭代会出现超过Int型,使用long
class Solution {
public:
int mySqrt(int x) {
if(x==0||x==1) return x;
int le=1,ri=x,ans=0;
while(ri>=le){
int mid=le+(ri-le)/2;
if((long long)mid*mid==x) return mid;
if((long long)mid*mid<x) {
le=mid+1;
ans=mid;
}
else ri=mid-1;
}
return ans;
}
};
或者使用指数形式
class Solution {
public:
int mySqrt(int x) {
if (x == 0) {
return 0;
}
int ans = exp(0.5 * log(x));
return ((long long)(ans + 1) * (ans + 1) <= x ? ans + 1 : ans);
}
};
70:爬楼梯
动态规划
class Solution {
public:
int climbStairs(int n) {
vector<int> dp(n+1);
if(n==1) return 1;
dp[1]=1;
dp[2]=2;
for(int i=3;i<=n;i++){
dp[i]=dp[i-2]+dp[i-1];
}
return dp[n];
}
};
简化:注意循环不能与变量使用一个参数!!!
class Solution {
public:
int climbStairs(int n) {
int i=0,j=1,a=0;
for(int k=1;k<=n;k++){
a=i+j;
i=j;
j=a;
}
return a;
}
};
75:颜色分类
使用库函数
class Solution {
public:
void sortColors(vector<int>& nums) {
sort(nums.begin(),nums.end());
}
};
使用两次循环求解
class Solution {
public:
void sortColors(vector<int>& nums) {
int i=0,j=0;
while(j<nums.size()){
if(nums[j]==0){
swap(nums[i],nums[j]);
i++;
}
j++;
}
j=i;
while(j<nums.size()){
if(nums[j]==1){
swap(nums[i],nums[j]);
i++;
}
j++;
}
}
};
78:子集
回溯法,记录所有节点,剩余集合为空则是叶子节点,可以返回。即index大于数组长度
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void backtravel(vector<int>& nums,int index){
result.push_back(path);
if(index>nums.size()-1) return;
for(int i=index;i<nums.size();i++){
path.push_back(nums[i]);
backtravel(nums,i+1);
path.pop_back();
}
}
vector<vector<int>> subsets(vector<int>& nums) {
backtravel(nums,0);
return result;
}
};
79:单词搜索
使用递归回溯,注意使用数组判断是否使用过
注意vector初值赋值方式。注意:::可能有好几个第一个数值,一定要确定所有情况都考虑
class Solution {
public:
bool exist(vector<vector<char>>& board, string word) {
rows = board.size(), columns = board[0].size();
for(int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
if (backtrack(board, word, i, j, 0)) return true; // 每个格子都进行回溯判断
}
}
return false;
}
private:
int rows, columns;
bool backtrack(vector<vector<char>>& board, string& word, int x, int y, int index) {
// 结束条件
// 越界或者当前字母位不相等
if (x >= rows || x < 0 || y >= columns || y < 0 || board[x][y] != word[index]) {
return false;
}
// 最后一个字母也相等,返回成功
if (index == word.size() - 1){
return true;
}
// 避免重复使用
board[x][y] = ' ';
// 回溯
if (backtrack(board, word, x - 1, y, index + 1)
|| backtrack(board, word, x + 1, y, index + 1)
|| backtrack(board, word, x, y - 1, index + 1)
|| backtrack(board, word, x, y + 1, index + 1))
{
return true;
}
// 如果不通,回溯至上一个状态
board[x][y] = word[index];
return false;
}
};
83:删除排序链表中的重复元素
注意考虑情况!!!要判断
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
if(head==NULL) return head;
ListNode* slow=head;
while(slow&&slow->next){
if(slow->val==slow->next->val){
slow->next=slow->next->next;
}
else slow=slow->next;
}
return head;
}
};
86:分隔链表
两个头结点
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* partition(ListNode* head, int x) {
ListNode* small=new ListNode(0);
ListNode* smallnode=small;
ListNode* large=new ListNode(0);
ListNode* largenode=large;
while(head){
if(head->val<x){
smallnode->next=head;
smallnode=smallnode->next;
}
else {
largenode->next=head;
largenode=largenode->next;
}
head=head->next;
}
smallnode->next=large->next;
largenode->next=NULL;
return small->next;
}
};
88:合并两个有序数组
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int i=m-1;
int j=n-1;
int l=m+n-1;
while(i>=0||j>=0){
if(i==-1) {
nums1[l]=nums2[j];
j--;
}
else if(j==-1){
nums1[l]=nums1[i];
i--;
}
else if(nums1[i]>nums2[j]){
nums1[l]=nums1[i];
i--;
}
else if(nums1[i]<=nums2[j]){
nums1[l]=nums2[j];
j--;
}
l--;
}
}
};
91:解码方法
使用动态规划
class Solution {
public:
int numDecodings(string s) {
if(s[0]=='0') return 0;
int pre=1;
int cur=1;
for(int i=1;i<s.size();i++){
int tmp=cur;
if(s[i]=='0'){
if(s[i-1]=='1'||s[i-1]=='2') cur=pre;
else return 0;
}
else if(s[i-1]=='1'||(s[i-1]=='2'&&s[i]<'7'&&s[i]>='0')) cur=cur+pre;
pre=tmp;
}
return cur;
}
};
92:反转链表
递归
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* travel(ListNode* pre1,ListNode* node){
if(node==NULL) return pre1;
ListNode* cur=node->next;
node->next=pre1;
return travel(node,cur);
}
ListNode* reverseBetween(ListNode* head, int left, int right) {
if(head==NULL) return head;
ListNode* dummy=new ListNode(0);
dummy->next=head;
ListNode* pre=dummy;
int m=right-left+1;
for(int i=1;i<left;i++){
pre=pre->next;
}
ListNode* later=pre;
for(int i=0;i<m;i++){
later=later->next;
}
ListNode* l=pre->next;
ListNode* curr=later->next;
pre->next=NULL;
later->next=NULL;
pre->next=travel(NULL,l);
l->next=curr;
return dummy->next;
}
};
迭代
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* reverseBetween(ListNode* head, int left, int right) {
int m=right-left+1;
ListNode *pre=NULL;
ListNode* result=head;
while(head&&--left){
pre=head;
head=head->next;
}
ListNode* tail=head;
ListNode* new1=NULL;
while(head&&m){
ListNode* cur=head->next;
head->next=new1;
new1=head;
head=cur;
m--;
}
tail->next=head;
if(pre) pre->next=new1;
else result=new1;
return result;
}
};
94:二叉树的中序遍历
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
void travel(TreeNode* node,vector<int>& result){
if(node==NULL) return;
travel(node->left,result);
result.push_back(node->val);
travel(node->right,result);
}
vector<int> inorderTraversal(TreeNode* root) {
vector<int> result;
if(root==NULL) return result;
travel(root,result);
return result;
}
};
95:不同的二叉搜索树2
动态规划!!关键是以谁为根节点
!!!!!注意:这里需要生成二叉搜索树,不能简单的生成次数
每次新增加的数字大于之前的所有数字,所以新增加的数字出现的位置只可能是根节点或者是根节点的右孩子,右孩子的右孩子,右孩子的右孩子的右孩子等等,总之一定是右边。其次,新数字所在位置原来的子树,改为当前插入数字的左孩子即可,因为插入数字是最大的。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
TreeNode* clone(TreeNode* node,int x){
if(node==NULL) return NULL;
int s=node->val+x;
TreeNode* root=new TreeNode(s); //不能修改原有数据
root->left=clone(node->left,x);
root->right=clone(node->right,x);
return root;
}
vector<TreeNode*> generateTrees(int n) {
vector<TreeNode*> dp[n+1];
if(n>0) dp[0].push_back(NULL);
if(n==0) return dp[0];
for(int i=1;i<=n;i++){
for(int j=1;j<=i;j++){
int left=j-1; //左边节点数
int right=i-j; //右边节点数
for (auto r : dp[right]) {
TreeNode* copyr = clone(r, j);
for (auto l : dp[left]) {
TreeNode* node=new TreeNode(j);
node->left=l;
node->right=copyr;
dp[i].push_back(node);
}
}
}
}
return dp[n];
}
};
96:不同的二叉搜索树
动态规划,分类是以j为根节点,左右两边的个数
class Solution {
public:
int numTrees(int n) {
vector<int> dp(n+1);
dp[0]=1;
for(int i=1;i<=n;i++){
for(int j=1;j<=i;j++){
dp[i]+=dp[j-1]*dp[i-j];
}
}
return dp[n];
}
};
98:验证二叉搜索树
使用容器
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
void travel(TreeNode* node,vector<int>& re){
if(node==NULL) return;
if(node->left) travel(node->left,re);
re.push_back(node->val);
if(node->right) travel(node->right,re);
}
bool isValidBST(TreeNode* root) {
if(root==NULL) return true;
vector<int> ans;
travel(root,ans);
for(int i=0;i<ans.size()-1;i++){
if(ans[i]>=ans[i+1]) return false;
}
return true;
}
};
102:二叉树的层序遍历
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
queue<TreeNode*> que;
vector<vector<int>> ans;
if(root!=NULL) que.push(root);
while(!que.empty()){
int s=que.size();
vector<int> re;
for(int i=0;i<s;i++){
TreeNode* node=que.front();
re.push_back(node->val);
que.pop();
if(node->left) que.push(node->left);
if(node->right) que.push(node->right);
}
ans.push_back(re);
}
return ans;
}
};
101:对称二叉树
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
bool isSymmetric(TreeNode* root) {
if(root==NULL) return false;
queue<TreeNode*> que;
que.push(root->left);
que.push(root->right);
while(!que.empty()){
TreeNode* lefto=que.front();que.pop();
TreeNode* righto=que.front();que.pop();
if(lefto==NULL&&righto==NULL) continue;
else if(lefto==NULL&&righto!=NULL) return false;
else if(lefto!=NULL&&righto==NULL) return false;
else if(lefto->val!=righto->val) return false;
que.push(lefto->left);
que.push(righto->right);
que.push(lefto->right);
que.push(righto->left);
}
return true;
}
};
141:环形链表
快慢指针
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool hasCycle(ListNode *head) {
if(head==NULL) return false;
ListNode* fast=head;
ListNode* slow=head;
while(fast!=NULL&&fast->next!=NULL){
fast=fast->next->next;
slow=slow->next;
if(fast==slow) return true;
}
return false;
}
};
96:不同的二叉搜索树
动态规划!dp[i]为i对应的二叉搜索树的数量,j为遍历头结点数量
class Solution {
public:
int numTrees(int n) {
vector<int> dp(n+1);
dp[0]=1;
for(int i=1;i<=n;i++){
for(int j=1;j<=i;j++){
dp[i]+=dp[j-1]*dp[i-j];
}
}
return dp[n];
}
};
102:二叉树的层序遍历
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
queue<TreeNode*> que;
vector<vector<int>> ans;
if(root!=NULL) que.push(root);
while(!que.empty()){
int s=que.size();
vector<int> re;
for(int i=0;i<s;i++){
TreeNode* node=que.front();
re.push_back(node->val);
que.pop();
if(node->left) que.push(node->left);
if(node->right) que.push(node->right);
}
ans.push_back(re);
}
return ans;
}
};
103:二叉树的锯齿层序遍历
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
queue<TreeNode*> que;
vector<vector<int>> ans;
if(root==NULL) return ans;
else que.push(root);
int x=1;
while(!que.empty()){
int s=que.size();
vector<int> re;
for(int i=0;i<s;i++){
TreeNode* node=que.front();
re.push_back(node->val);
que.pop();
if(node->left) que.push(node->left);
if(node->right) que.push(node->right);
}
if(x==-1) reverse(re.begin(),re.end());
ans.push_back(re);
x=x*(-1);
}
return ans;
}
};
双端队列
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
queue<TreeNode*> que;
vector<vector<int>> ans;
if(root==NULL) return ans;
else que.push(root);
int x=1;
while(!que.empty()){
int s=que.size();
deque<int> re;
for(int i=0;i<s;i++){
TreeNode* node=que.front();
if(x==1) re.push_back(node->val);
if(x==-1) re.push_front(node->val);
que.pop();
if(node->left) que.push(node->left);
if(node->right) que.push(node->right);
}
ans.push_back(vector<int>{re.begin(),re.end()});
x=x*(-1);
}
return ans;
}
};
142:环形链表2
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
int pose=0;
ListNode* fast=head;
ListNode* slow=head;
while(fast!=NULL&&fast->next!=NULL){
slow=slow->next;
fast=fast->next->next;
if(slow==fast){
ListNode* index1=fast;
ListNode* index2=head;
while(index1!=index2){
index1=index1->next;
index2=index2->next;
}
return index1;
}
}
return NULL;
}
};
使用双端队列
144:前序遍历二叉树
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
void travel(TreeNode* node,vector<int>& ans){
if(node==NULL) return;
ans.push_back(node->val);
travel(node->left,ans);
travel(node->right,ans);
}
vector<int> preorderTraversal(TreeNode* root) {
vector<int> ans;
if(root==NULL) return ans;
travel(root,ans);
return ans;
}
};
160:相交链表
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
set<ListNode*> m;
while(headA){
m.insert(headA);
headA=headA->next;
}
while(headB){
if(m.find(headB)!=m.end()) return headB;
headB=headB->next;
}
return NULL;
}
};
优化:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
int a=0,b=0;
ListNode* headA1=headA;
ListNode* headB1=headB;
while(headA1){
headA1=headA1->next;
a++;
}
while(headB1){
headB1=headB1->next;
b++;
}
if(a<b) {
for(int i=0;i<b-a;i++) headB=headB->next;
}
else for(int i=0;i<a-b;i++) headA=headA->next;
while(headA&&headB){
if(headA==headB) return headA;
headA=headA->next;
headB=headB->next;
}
return NULL;
}
};
206:反转链表
使用递归
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* travel(ListNode* pre,ListNode* cur){
if(cur==NULL) return pre;
ListNode* node=cur->next;
cur->next=pre;
return travel(cur,node);
}
ListNode* reverseList(ListNode* head) {
if(head==NULL) return head;
ListNode* node=travel(NULL,head);
return node;
}
};
使用迭代
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* pre=NULL;
while(head){
ListNode* node=head->next;
head->next=pre;
pre=head;
head=node;
}
return pre;
}
};
226:反转二叉树
也可以直接使用swap
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
void travel(TreeNode* node){
if(node==NULL) return ;
TreeNode* cur=node->left;
node->left=node->right;
node->right=cur;
travel(node->left);
travel(node->right);
}
TreeNode* invertTree(TreeNode* root) {
if(root==NULL) return root;
travel(root);
return root;
}
};
239:滑动窗口最大值
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
vector<int> ans;
int s=INT_MIN;
if(nums.size()==0) return ans;
for(int i=0;i<=nums.size()-k;i++){
s=INT_MIN;
for(int j=0;j<k;j++){
s=max(s,nums[i+j]);
}
ans.push_back(s);
}
return ans;
}
};
使用优先队列,避免超过时间限制
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
vector<int> ans;
int m=nums.size();
priority_queue<pair<int,int>> q;
for(int i=0;i<k;i++){
q.emplace(nums[i],i);
}
ans.push_back(q.top().first);
for(int i=k;i<m;i++){
q.emplace(nums[i],i);
while(q.top().second<i-k+1){
q.pop();
}
ans.push_back(q.top().first);
}
return ans;
}
};
255:用队列实现栈
class MyStack {
public:
queue<int> que1;
queue<int> que2;
/** Initialize your data structure here. */
MyStack() {
}
/** Push element x onto stack. */
void push(int x) {
que1.push(x);
}
/** Removes the element on top of the stack and returns that element. */
int pop() {
if(que1.empty()) return -1;
int m=que1.size();
for(int i=0;i<m-1;i++){
int x=que1.front();
que1.pop();
que2.push(x);
}
int x=que1.front();
que1.pop();
que1=que2;
while(!que2.empty()){
que2.pop();
}
return x;
}
/** Get the top element. */
int top() {
return que1.back();
}
/** Returns whether the stack is empty. */
bool empty() {
return que1.empty();
}
};
/**
* Your MyStack object will be instantiated and called as such:
* MyStack* obj = new MyStack();
* obj->push(x);
* int param_2 = obj->pop();
* int param_3 = obj->top();
* bool param_4 = obj->empty();
*/
322:零钱兑换
动态规划问题
class Solution {
public:
int coinChange(vector<int>& coins, int amount) {
int s=coins.size();
vector<int> dp(amount+1,INT_MAX);
if(amount==0) return 0;
if(s==0) return 0;
dp[0]=0;
for(int i=1;i<=amount;i++){
for(int j=0;j<s;j++){
if(i-coins[j]<0) continue;
dp[i]=min(dp[i],dp[i-coins[j]]+1);
}
}
return dp[amount];
}
};
343:整数拆分
动态规划,注意!!!一定要观察,dp[i]是对i进行拆分的最大乘积,找到对应的递推关系
class Solution {
public:
int integerBreak(int n) {
vector<int> dp(n+1);
dp[2]=1;
for(int i=3;i<=n;i++){
for(int j=1;j<i-1;j++){
dp[i]=max(dp[i],max(j*(i-j),j*dp[i-j]));
}
}
return dp[n];
}
};
**
232:用栈实现队列
**
class MyQueue {
public:
stack<int> stk1;
stack<int> stk2;
/** Initialize your data structure here. */
MyQueue() {
}
/** Push element x to the back of queue. */
void push(int x) {
stk1.push(x);
}
/** Removes the element from in front of queue and returns that element. */
int pop() {
if(stk2.empty()) {
while(!stk1.empty()){
stk2.push(stk1.top());
stk1.pop();
}
}
int x=stk2.top();
stk2.pop();
return x;
}
/** Get the front element. */
int peek() {
if(stk2.empty()) {
while(!stk1.empty()){
stk2.push(stk1.top());
stk1.pop();
}
}
int x=stk2.top();
return x;
}
/** Returns whether the queue is empty. */
bool empty() {
return stk1.empty()&&stk2.empty();
}
};
/**
* Your MyQueue object will be instantiated and called as such:
* MyQueue* obj = new MyQueue();
* obj->push(x);
* int param_2 = obj->pop();
* int param_3 = obj->peek();
* bool param_4 = obj->empty();
*/
509:斐波那契数
使用动态规划,注意一定要看边界,要么dp设置大点要么判断n为0情况
class Solution {
public:
int fib(int n) {
vector<int> dp(n+5);
dp[0]=0;
dp[1]=1;
for(int i=2;i<=n;i++){
dp[i]=dp[i-1]+dp[i-2];
}
return dp[n];
}
};
最长子序列
class Solution {
public:
/**
* longest common substring
* @param str1 string字符串 the string
* @param str2 string字符串 the string
* @return string字符串
*/
string LCS(string str1, string str2) {
// write code here
int m=str1.size();
int n=str2.size();
string s;
int max=0,end=0;
vector<vector<int>> dp(m+1,vector<int>(n+1,0));
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
if(str1[i-1]==str2[j-1]){
dp[i][j]=dp[i-1][j-1]+1;
}
else dp[i][j]=0;
if(dp[i][j]>max){
max=dp[i][j];
end=j-1;
}
}
}
if(max==0) return "-1";
else s=str2.substr(end-max+1,max);
return s;
}
};