本页开始出现大量的动态规划中等题,我对自己的要求就是中等难度的会做就好,困难的就随缘吧。
51. N-Queens
52. N-Queens II
53. Maximum Subarray
动态规划版:
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int k=0,max1=nums[0];
for(int i=0;i<nums.size();i++)
{
if(k+nums[i]<0)
{
k=0;
max1=max(nums[i],max1);
}
else
{
k+=nums[i];
max1=max(k,max1);
}
}
return max1;
}
};
分治版:
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int low=0,high=nums.size()-1;
return dc(nums,low,high);
}
int dc(vector<int>& nums,int low,int high){
int mid=(low+high)/2;
if(mid==high)
return nums[mid];
else
{
int a=dc(nums,low,mid);
int b=digui(nums,low,mid,high);
int c=dc(nums,mid+1,high);
return max(max(a,b),c);
}
}
int digui(vector<int>& nums,int low,int mid,int high){
int max1=INT_MIN;
int sum1=0;
for(int i=mid;i>=low;i--)
{
sum1+=nums[i];
max1=max(max1,sum1);
}
int max2=INT_MIN;
int sum2=0;
for(int i=mid+1;i<=high;i++)
{
sum2+=nums[i];
max2=max(max2,sum2);
}
return max1+max2;
}
};
注:简单题,动态规划时间复杂度O(n)和分治法O(nlog(n))都可以求解,就这题给我弄个分治法比动态规划快我也是很服。DP faster than 63.89% ,DC faster than 64.89%。
54. Spiral Matrix
class Solution {
public:
vector<int> spiralOrder(vector<vector<int>>& matrix) {
vector<int> a;
if(matrix.size()==0||matrix[0].size()==0)
return a;
int top=0,down=matrix.size(),left=0,right=matrix[0].size();
while(left<right||top<down)
{
for(int i=left;i<right&&top<down;i++)
a.push_back(matrix[top][i]);
top++;
for(int i=top;i<down&&left<right;i++)
a.push_back(matrix[i][right-1]);
right--;
for(int i=right-1;i>=left&&top<down;i--)
a.push_back(matrix[down-1][i]);
down--;
for(int i=down-1;i>=top&&left<right;i--)
a.push_back(matrix[i][left]);
left++;
}
return a;
}
};
注:中等题,这题主要关注循环的边界条件,否则极容易越界或重复计数。 faster than 100.00%。
55. Jump Game
动态规划版:
class Solution {
public:
bool canJump(vector<int>& nums) {
vector<int> a(nums.size(),-1);
for(int i=nums.size()-1;i>=0;i--)
{
for(int j=0;j<=nums[i];j++)
{
if(i+j>=nums.size()-1)
{
a[i]=1;
break;
}
if(a[i+j]==1)
a[i]=1;
}
if(a[i]==-1)
a[i]=0;
}
return a[0];
}
};
记忆化搜索版:
class Solution {
public:
bool canJump(vector<int>& nums) {
vector<int> a(nums.size()+1,-1);
return digui(nums,a,0);
}
int digui(const vector<int>& nums,vector<int> &a,int n)
{
if(a[n]!=-1)
return a[n];
if(n>=nums.size()-1)
return 1;
for(int i=1;i<=nums[n];i++)
{
int p=digui(nums,a,n+i);
a[n]=p==1?1:a[n];
}
if(a[n]==-1)
a[n]=0;
return a[n];
}
};
注:中等题,这题一瞅就是动态规划,还是找递推方程,这题的优秀解太变态了,看清自己定位的情况下果断放弃学习他那个解法,老实一步一步来。。。 faster than 19.37%。
56. Merge Intervals
/**
* Definition for an interval.
* struct Interval {
* int start;
* int end;
* Interval() : start(0), end(0) {}
* Interval(int s, int e) : start(s), end(e) {}
* };
*/
class Solution {
public:
static bool compare(Interval a,Interval b){
if(a.start != b.start)
return a.start<b.start;
else
return a.end<b.end;
}
vector<Interval> merge(vector<Interval>& intervals) {
if(intervals.size()==0)
return intervals;
vector<Interval> a;
sort(intervals.begin(),intervals.end(),compare);
for(int i=0;i<intervals.size();i++)
{
Interval b;
b.start=intervals[i].start;
int max1= intervals[i].end;
while(i+1<intervals.size()&&max1>=intervals[i+1].start)
{
if(max1<intervals[++i].end)
if(intervals[i].end<intervals[i+1].start)
break;
max1=max(intervals[i].end,max1);
}
max1=max(intervals[i].end,max1);
b.end=max1;
a.push_back(b);
}
return a;
}
};
注:中等题,做的我没心气了,错了6次才成功,合并区间就判断start和end的值就好了,具体都懂。另外就是sort函数的第三个参数,之前遇到过一次忘了,第三个参数的函数定义前需要加static。faster than 44.20%。
57. Insert Interval
/**
* Definition for an interval.
* struct Interval {
* int start;
* int end;
* Interval() : start(0), end(0) {}
* Interval(int s, int e) : start(s), end(e) {}
* };
*/
class Solution {
public:
static bool cmp(Interval a, Interval b){
if(a.start != b.start)
return a.start<b.start;
else
return a.end<b.end;
}
vector<Interval> merge(vector<Interval>& intervals) {
vector<Interval> a;
if(intervals.size()==0)
return a;
intervals.push_back(Interval(INT_MAX,INT_MAX));
sort(intervals.begin(),intervals.end(),cmp);
for(int i=0;i<intervals.size()-1;i++)
{
if(intervals[i].end>=intervals[i+1].start)
{
if(intervals[i].end==INT_MAX)
a.push_back(intervals[i]);
intervals[i+1].start=intervals[i].start;
if(intervals[i].end>=intervals[i+1].end)
intervals[i+1].end=intervals[i].end;
}
else
a.push_back(intervals[i]);
}
return a;
}
vector<Interval> insert(vector<Interval>& intervals, Interval newInterval) {
intervals.push_back(newInterval);
return merge(intervals);
}
};
58. Length of Last Word
class Solution {
public:
int lengthOfLastWord(string s) {
int sum=0;
for(int i=s.size()-1;i>=0;i--)
{
if(s[i]==' ')
{
if(sum!=0)
break;
}
else sum++;
}
return sum;
}
};
注:简单题,唯一需要注意的就是结尾有空格的情况,这时空格应该不算数。faster than 100.00% 。
59. Spiral Matrix II
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
if(n==0)
return {};
vector<vector<int>> matrix(n,vector<int>(n,1));
int top=0,down=matrix.size(),left=0,right=matrix[0].size();
int k=1;
while(left<right||top<down)
{
for(int i=left;i<right&&top<down;i++)
matrix[top][i]=k++;
top++;
for(int i=top;i<down&&left<right;i++)
matrix[i][right-1]=k++;
right--;
for(int i=right-1;i>=left&&top<down;i--)
matrix[down-1][i]=k++;
down--;
for(int i=down-1;i>=top&&left<right;i--)
matrix[i][left]=k++;
left++;
}
return matrix;
}
};
注:中等题,在54题的基础上改改就好了,没啥难度。faster than 100.00% 。
60. Permutation Sequence
class Solution {
public:
string getPermutation(int n, int k) {
string a;
string nums;
vector<int> p{0};
for(int i=1;i<=n;i++)
nums+=to_string(i);
while(--k)
nextPermutation(nums);
return nums;
}
void nextPermutation(string& nums) {
int k=-1,p;
for(int i=nums.size()-1;i>0;i--)
{
if(nums[i]>nums[i-1])
{
k=i-1;
break;
}
}
if(k<0)
reverse(nums.begin(), nums.end());
else{
for(int i=nums.size()-1;i>0;i--)
{
if(nums[i]>nums[k])
{
p=i;
break;
}
}
swap(nums[p],nums[k]);
reverse(nums.begin()+k+1, nums.end());
}
}
};
注:中等题,这题直接用了第31题的代码,结果很烂,懒得想规律了。faster than 13.78% 。
61. Rotate List
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* rotateRight(ListNode* head, int k) {
ListNode* p=head;
ListNode* q=head;
ListNode* m=head;
int j=0;
while(m)
{
j++;
m=m->next;
}
if(j==0||!(k%j))
return head;
k%=j;
while(k--)
q=q->next;
while(q->next)
{
q=q->next;
p=p->next;
}
m=p->next;
p->next=NULL;
ListNode* n=m;
while(n->next)
n=n->next;
n->next=head;
return m;
}
};
注:中等题,这种题我总是用自己的先验知识来评估输入的傻逼程度,就这题能给我弄出来个空指针输入我也是很服气好吧。先求出链表的总长度,然后看看输入的k和总长度的关系,再利用双指针找到需要翻转的节点就好了。faster than 98.47% 。
62. Unique Paths
动态规划版:
class Solution {
public:
int uniquePaths(int m, int n) {
vector<vector<int>> a(n,vector<int>(m,1));
for(int i=1;i<n;i++)
for(int j=1;j<m;j++)
a[i][j]=a[i-1][j]+a[i][j-1];
return a[n-1][m-1];
}
};
记忆化搜索版:
class Solution {
public:
int uniquePaths(int m, int n) {
vector<vector<int>> a(n,vector<int>(m,-1));
return digui(a,0,0);
}
int digui(vector<vector<int>> &a,int p,int q)
{
if(p>=a.size()||q>=a[0].size())
return 0;
if(a[p][q]!=-1)
return a[p][q];
if(p==a.size()-1&&q==a[0].size()-1)
return 1;
a[p][q]=digui(a,p,q+1)+digui(a,p+1,q);
return a[p][q];
}
};
注:如何去认定这题需要动态规划?在研究题型的时候就要想这题是否出现了大量的重复计算,如果出现了,大概率是要用动态规划解法的。faster than 100.00% 。
63. Unique Paths II
记忆化搜索版:
class Solution {
public:
int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
vector<vector<int>> a(obstacleGrid.size(),vector<int>(obstacleGrid[0].size(),-1));
return digui(obstacleGrid,a,0,0);
}
int digui(vector<vector<int>>& obstacleGrid,vector<vector<int>> &a,int p,int q)
{
if(p>=a.size()||q>=a[0].size()||obstacleGrid[p][q]==1)
return 0;
if(a[p][q]!=-1)
return a[p][q];
if(p==a.size()-1&&q==a[0].size()-1)
return 1;
a[p][q]=digui(obstacleGrid,a,p,q+1)+digui(obstacleGrid,a,p+1,q);
return a[p][q];
}
};
注:中等题,62题加了个限制条件了,动态规划不会。。faster than 35.84% 。
64. Minimum Path Sum
class Solution {
public:
int minPathSum(vector<vector<int>>& grid) {
vector<vector<int>> a=grid;
for(int i=0;i<grid.size();i++)
{
for(int j=0;j<grid[0].size();j++)
{
if(i+1<grid.size())
grid[i+1][j]=grid[i+1][j]+grid[i][j];
if(j+1<grid[0].size())
{
if(a[i][j+1]==grid[i][j+1])
grid[i][j+1]=grid[i][j+1]+grid[i][j];
else grid[i][j+1]=min(grid[i][j+1],a[i][j+1]+grid[i][j]);
}
}
}
return grid[grid.size()-1][grid[0].size()-1];
}
};
注:中等题,动态规划,跟120题一样的思路。faster than 100% 。
65. Valid Number
注:困难题,62题加了个限制条件了,动态规划不会。。faster than 35.84% 。
66. Plus One
class Solution {
public:
vector<int> plusOne(vector<int>& digits) {
int jinwei=1;
for(int i=digits.size()-1;i>=0;i--)
{
digits[i]+=jinwei;
jinwei=digits[i]/10;
digits[i]%=10;
}
if(jinwei==1)
digits.insert(digits.begin(),1);
return digits;
}
};
注:简单题,唯一需要注意的就是溢出的情况,此时在头结点插入一个1就好了。faster than 100.00% 。
67. Add Binary
class Solution {
public:
string addBinary(string a, string b) {
int i=0,j=0,jinwei=0;
string s;
reverse(a.begin(),a.end());
reverse(b.begin(),b.end());
while(i<a.size()||j<b.size())
{
int c=0,d=0;
if(i<a.size())
{
c=a[i]-'0';
i++;
}
if(j<b.size())
{
d=b[j]-'0';
j++;
}
int k=c+d+jinwei;
s+=to_string(k%2);
jinwei=k/2;
}
if(jinwei)
s+="1";
reverse(s.begin(),s.end());
return s;
}
};
注:简单题,字符串倒置后就挨个加吧。faster than 100.00% 。
69. Sqrt(x)
class Solution {
public:
int mySqrt(int x) {
if(x==0||x==1)
return x;
int low=0,high=x;
while(high>=low)
{
int mid=(high+low)/2;
if(pow(mid,2)<x)
low=mid+1;
else if(pow(mid,2)>x)
high=mid-1;
else return mid;
}
return --low;
}
};
注:简单题,二分法的典型应用,其实这段代码是有bug的,mid的二次幂很容易越界,但是即使越界后的数也比x大,所以就当这个bug不存在了。。。faster than 53.35% 。
70. Climbing Stairs
动态规划版:
class Solution {
public:
int climbStairs(int n) {
vector<int> a(n+1,-1);
for(int i=0;i<a.size();i++)
{
if(i==0||i==1)
a[i]=1;
else a[i]=a[i-1]+a[i-2];
}
return a[a.size()-1];
}
};
记忆化搜索版:
class Solution {
public:
int climbStairs(int n) {
vector<int> a(n+1,-1);
return digui(a,n);
}
int digui(vector<int> &a,int n)
{
if(a[n]!=-1)
return a[n];
if(n==0||n==1)
return 1;
a[n]=digui(a,n-1)+digui(a,n-2);
return a[n];
}
};
注:简单题,典型的动态规划算法,暴力解法一定是爆炸的。重点是要找递推方程式,这题的递推方程式跟斐波那契数列一样,第一次编可以用递归版,这个更清晰 。
Runtime: 4 ms, faster than 77.97% of C++ online submissions for Climbing Stairs.
Memory Usage: 8.4 MB, less than 48.14% of C++ online submissions forClimbing Stairs.
71. Simplify Path
class Solution {
public:
string simplifyPath(string path) {
vector<string> v;
int i = 0;
while (i < path.size()) {
while (path[i] == '/' && i < path.size()) ++i;
if (i == path.size()) break;
int start = i;
while (path[i] != '/' && i < path.size()) ++i;
int end = i - 1;
string s = path.substr(start, end - start + 1);
if (s == "..") {
if (!v.empty()) v.pop_back();
} else if (s != ".") {
v.push_back(s);
}
}
if (v.empty()) return "/";
string res;
for (int i = 0; i < v.size(); ++i) {
res += '/' + v[i];
}
return res;
}
};
注:中等题,这种题以后就不做了。faster than XX% 。
72. Edit Distance
注:中等题,这种题以后就不做了。faster than XX% 。
73. Set Matrix Zeroes
class Solution {
public:
void setZeroes(vector<vector<int>>& matrix) {
int hang=-1,lie=-1;
for(int i=0;i<matrix.size();i++)
{
for(int j=0;j<matrix[0].size();j++)
{
if(matrix[i][j]==0)
{
hang=i;
lie=j;
break;
}
}
}
if(hang==-1||lie==-1)
return;
for(int i=0;i<matrix.size();i++)
{
for(int j=0;j<matrix[0].size();j++)
{
if(matrix[i][j]==0)
{
matrix[i][lie]=0;
matrix[hang][j]=0;
}
}
}
for(int i=0;i<matrix.size();i++)
{
if(matrix[i][lie]==0&&i!=hang)
{
for(int j=0;j<matrix[0].size();j++)
matrix[i][j]=0;
}
}
for(int i=0;i<matrix[0].size();i++)
{
if(matrix[hang][i]==0)
{
for(int j=0;j<matrix.size();j++)
matrix[j][i]=0;
}
}
for(int j=0;j<matrix[0].size();j++)
matrix[hang][j]=0;
}
};
注:中等题,本题要求原地算法,思路就是找到数组中的一个0,用它的横轴纵轴储存其他0的信息。faster than 27.54% 。
74. Search a 2D Matrix
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
if(matrix.size()==0||matrix[0].size()==0)
return false;
int high=matrix.size()-1,low=0,mid;
while(high>=low)
{
mid=(high+low)/2;
if(matrix[mid][0]<target)
low=mid+1;
else if(matrix[mid][0]>target)
high=mid-1;
else return true;
}
int hang=low-1;
if(hang<0)
return false;
high=matrix[0].size()-1,low=0;
while(high>=low)
{
mid=(high+low)/2;
if(matrix[hang][mid]<target)
low=mid+1;
else if(matrix[hang][mid]>target)
high=mid-1;
else return true;
}
return false;
}
};
注:中等题,两次二分查找就好了,第一次在每一行头结点找,第二次在行内找。faster than 97.19% 。
75. Sort Colors
class Solution {
public:
void sortColors(vector<int>& nums) {
int i=0,j=0,k=0;
for(int p=0;p<nums.size();p++)
{
if(nums[p]==0)
{
nums[k++]=2;
nums[j++]=1;
nums[i++]=0;
}
else if(nums[p]==1)
{
nums[k++]=2;
nums[j++]=1;
}
else if(nums[p]==2)
nums[k++]=2;
}
}
};
注:中等题,我用的是O(n)复杂度的算法,从前到后遍历,用三指针代表012的位置,更快的算法有双指针算法,left指针代表0,right代表2,中间的就是1。faster than 34.54% 。
76. Minimum Window Substring
class Solution {
public:
string minWindow(string s, string t) {
unordered_map<char,int> a;
string k;
int count=0,left=0,right=0,min=INT_MAX,sum;
for(int i=0;i<t.size();i++)
a[t[i]]++;
while(right<s.size())
{
if(a.find(s[right])==a.end())
{
right++;
continue;
}
else
{
a[s[right]]--;
if(a[s[right]]>=0)
count++;
if(count==t.size())
{
while(left<right)
{
if(a.find(s[left])==a.end())
{
left++;
continue;
}
if(a[s[left]]<0)
{
a[s[left]]++;
left++;
continue;
}
else break;
}
sum=right-left+1;
if(sum<min)
{
min=sum;
k=s.substr(left,sum);
}
}
right++;
}
}
return k;
}
};
https://blog.csdn.net/zhangxiao93/article/details/49892665
注:困难题,思路就是滑窗法加哈希表,本题引入了count值来记录字符个数,这点我没有想到,满足不了线性时间复杂度,所以参考了别人的博客,博客里很详细,我就不解释了,速度快的用的是数组存储。faster than 42.58% 。
77. Combinations
class Solution {
public:
vector<vector<int>> combine(int n, int k) {
vector<vector<int>> a;
vector<int> b;
digui(a,b,n,k,1);
return a;
}
void digui(vector<vector<int>> &a,vector<int> &b,int n, int k,int p){
if(b.size()==k)
{
a.push_back(b);
return;
}
for(int i=p;i<=n;i++)
{
b.push_back(i);
digui(a,b,n,k,i+1);
b.pop_back();
}
}
};
注:中等题,简单的递归就可解,不废话了。faster than 45.01% 。
78. Subsets
class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
vector<vector<int>> a;
vector<int> b;
for(int i=0;i<=nums.size();i++)
digui(nums,a,b,i,0);
return a;
}
void digui(vector<int>& nums,vector<vector<int>> &a,vector<int> &b,int k,int p){
if(b.size()==k)
{
a.push_back(b);
return;
}
for(int i=p;i<nums.size();i++)
{
b.push_back(nums[i]);
digui(nums,a,b,k,i+1);
b.pop_back();
}
}
};
注:中等题,第77题加个for循环就行了,如果连着做没啥难度,单独做的话兴许想不到。faster than 100.00% 。
79. Word Search
class Solution {
public:
bool exist(vector<vector<char>>& board, string word) {
if(word.size()==0)
return true;
if(board.size()==0 || board[0].size()==0)
return false;
vector<vector<int>> cache(board.size(), vector<int>(board[0].size(), 0));
for(int i=0;i<board.size();i++)
for(int j=0;j<board[0].size();j++)
if(isexist(board, cache, word, i, j, 0))
return true;
return false;
}
bool isexist(vector<vector<char>>& board, vector<vector<int>>& cache, string& word, int i, int j, int k)
{
// if(k==word.size())
// return true;
if(board[i][j] == word[k])
{
cache[i][j] = 1;
if(k+1==word.size())
return true;
if(i+1<board.size() && !cache[i+1][j] && isexist(board, cache, word, i+1, j, k+1))
return true;
if(j+1<board[0].size() && !cache[i][j+1] && isexist(board, cache, word, i, j+1, k+1))
return true;
if(i-1>=0 && !cache[i-1][j] && isexist(board, cache, word, i-1, j, k+1))
return true;
if(j-1>=0 && !cache[i][j-1] && isexist(board, cache, word, i, j-1, k+1))
return true;
cache[i][j] = 0;
}
return false;
}
};
注:中等题,深度优先搜索法,递归去找。
Runtime: 24 ms, faster than 90.99% of C++ online submissions for Word Search.
Memory Usage: 10.6 MB, less than 76.82% of C++ online submissions forWord Search.
80. Remove Duplicates from Sorted Array II
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
int p=0;
bool q=false;
for(int i=0;i<nums.size();i++)
{
if(i+1<nums.size()&&nums[i]==nums[i+1])
{
if(q)
continue;
else
{
q=true;
nums[p++]=nums[i];
}
}
else
{
q=false;
nums[p++]=nums[i];
}
}
return p;
}
};
注:中等题,本题需要保存两个重复数,引入bool q来判断,p为滑动指针。faster than 100.00% 。
81. Search in Rotated Sorted Array II
class Solution {
public:
bool search(vector<int>& nums, int target) {
int high=nums.size()-1,low=0,mid;
while(high>=low)
{
mid=(high+low)/2;
if(nums[mid]==target)
return true;
else if(nums[mid]<nums[high])
{
if(nums[mid]<target&&nums[high]>=target)
low=mid+1;
else high=mid-1;
}
else if(nums[mid]>nums[high])
{
if(nums[low] <= target && nums[mid] > target)
high = mid-1;
else
low = mid + 1;
}
else high--;
}
return false;
}
};
注:中等题,33题的又一子问题,在找有序子区间的同时要避免nums[mid]等于nums[high]的情况,如果发生,则high减一。faster than 29.73% 。
82. Remove Duplicates from Sorted List II
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
ListNode* m= new ListNode(0);
m->next=head;
ListNode* p=m;
int k=INT_MAX;
bool q=false;
while(p->next)
{
if(p->next->next&&p->next->next->val==p->next->val)
{
k=p->next->val;
p->next=p->next->next;
q=true;
}
else if(q&&k==p->next->val)
p->next=p->next->next;
else p=p->next;
}
return m->next;
}
};
注:中等题,大体与83题相似,但额外考虑一下怎么把剩下的那个重复元素删除就好了,我的想法是引入了一个int值,当节点与重复的int值相等时就删了它,但是这个int值极有可能和测试用例里的撞上,所以选择即使撞上也就最后一个撞上的INT_MAX,期望不会撞上。但果不其然,跟测试用例[-2147483648,2147483647,2]撞上了,所以被逼无奈引入了bool值。但是测试大哥,这题不是说好的排序链表嘛,你这个测试用例什么情况?!faster than 100.00% 。
83. Remove Duplicates from Sorted List
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
ListNode* m = new ListNode(0);
m->next = head;
ListNode* p = m;
while(p->next && p->next->next)
{
if(p->next->val == p->next->next->val)
p->next = p->next->next;
else p = p->next;
}
return m->next;
}
};
注:简单题,自己设定一个链表头,一个节点接着一个节点遍历就好了,遇到重复的就删掉。
Runtime: 12 ms, faster than 87.40% of C++ online submissions for Remove Duplicates from Sorted List.
Memory Usage: 9.3 MB, less than 23.66% of C++ online submissions forRemove Duplicates from Sorted List.
86. Partition List
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* partition(ListNode* head, int x) {
ListNode* m=new ListNode(0);
m->next=head;
ListNode* p=m;
while(p->next)
{
if(p->next->val<x)
p=p->next;
else break;
}
ListNode* q=p;
while(q&&q->next)
{
if(q->next->val<x)
{
ListNode* n=new ListNode(q->next->val);
n->next=p->next;
p->next=n;
p=p->next;
q->next=q->next->next;
}
else q=q->next;
}
return m->next;
}
};
注:中等题,双指针并行,一个指向小于x的节点,另一个向后遍历,遇到小于x的节点则拼接到第一个指针的后面,并删除。faster than 28.52% 。
88. Merge Sorted Array
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int i=0,j=0;
while(j<n)
{
if(i<m&&nums1[i]<=nums2[j])
i++;
else
{
nums1.erase(nums1.end()-1);
nums1.insert(nums1.begin()+i,nums2[j]);
j++;
i++;
m++;
}
}
}
};
注:简单题,我这个程序写出来就知道很慢,快的程序是从后往前赋值,这样就不用删除插入了。faster than 13.33% 。
89. Gray Code
class Solution {
public:
void dfs(vector<int>& ans, int cur, int n){
if(n == 0) {ans.push_back(0); return;}//只有一位格雷,特别处理
if(cur > n) return;
if(cur == 1){
ans.push_back(0);
ans.push_back(1);
dfs(ans, cur+1, n);
}else{
int len = ans.size();//循环前确定ans的长度,在循环中,ans的长度是变化的
for(int j = 0; j < len; j++)
ans.push_back(ans[len-j-1] + pow(2, cur-1));
dfs(ans, cur+1, n);
}
}
vector<int> grayCode(int n) {
vector<int> ans;
dfs(ans, 1, n);
return ans;
}
};
注:中等题,。faster than XX% 。
90. Subsets II
class Solution {
public:
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
vector<vector<int>> a;
vector<int> b;
sort(nums.begin(),nums.end());
for(int i=0;i<=nums.size();i++)
digui(nums,a,b,i,0);
return a;
}
void digui(vector<int>& nums,vector<vector<int>> &a,vector<int> &b,int k,int p){
if(b.size()==k)
{
a.push_back(b);
return;
}
for(int i=p;i<nums.size();i++)
{
if(i-1>=p&&nums[i]==nums[i-1])
continue;
b.push_back(nums[i]);
digui(nums,a,b,k,i+1);
b.pop_back();
}
}
};
注:中等题,跟78题类似,但需要去重,去重的方法跟之前的第40题思路一致。faster than 52.59% 。
91. Decode Ways
记忆化搜索:
class Solution {
public:
int numDecodings(string s) {
vector<int> a(s.size(),-1);
if(s.size()==0)
return 0;
return digui(s,0,a);
}
int digui(string s,int n,vector<int>& a)
{
int k=0;
if(n>s.size()||s[n]=='0')
return 0;
if(n==s.size())
return 1;
if(a[n]!=-1)
return a[n];
if(n+2<=s.size()&&atoi(s.substr(n,2).c_str())<=26)
{
if(s[n+1]!='0')
a[n]=digui(s,n+1,a)+digui(s,n+2,a);
else a[n]=digui(s,n+2,a);
}
else if(n+2<=s.size()&&atoi(s.substr(n,2).c_str())>26&&s[n+1]=='0')
return 0;
else a[n]=digui(s,n+1,a);
return a[n];
}
};
注:中等题,典型的动态规划解法,脑袋抽了,做到一半以为不用动态规划,直接递归回溯果然超时。。需要注意的是其中字符'0'的问题。faster than 52.59% 。
92. Reverse Linked List II
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseBetween(ListNode* head, int m, int n) {
ListNode* h=new ListNode(0);
h->next=head;
ListNode* p=h;
int c=m;
while(--c)
p=p->next;
ListNode* g=p->next;
ListNode* q=p->next;
int i=n-m;
while(i--)
q=q->next;
ListNode* k=q->next;
q->next=NULL;
ListNode* a=NULL;
ListNode* b=g->next;
while(1)
{
g->next=a;
a=g;
g=b;
if(!g)
break;
b=b->next;
}
p->next=a;
i=n-m;
while(i--)
a=a->next;
a->next=k;
return h->next;
}
};
注:中等题,简化版的第25题,没啥大区别。faster than 100.00% 。
93. Restore IP Addresses
class Solution {
public:
vector<string> restoreIpAddresses(string s) {
string b;
vector<string> a;
digui(s,a,b,1,0);
return a;
}
void digui(string s,vector<string>& a,string b,int k,int n)
{
if(k==5)
{
if(b.size()-4==s.size())
a.push_back(b.substr(1));
return;
}
string q;
for(int i=0;i<3;i++)
{
if(i+n>=s.size())
return ;
q.push_back(s[i+n]);
if(atoi(q.c_str())>255)
return ;
if(q.size()>1&&q[0]=='0')
return ;
digui(s,a,b+"."+q,k+1,n+i+1);
}
}
};
注:中等题,典型的递归回溯法,唯一需要注意的是边界条件,总共4位,每位不得超过255,每位数字除0外开头不能为0。faster than 100.00% 。
94. Binary Tree Inorder Traversal
递归版:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> a;
digui(a,root);
return a;
}
void digui(vector<int> &a,TreeNode* root)
{
if(!root)
return ;
digui(a,root->left);
a.push_back(root->val);
digui(a,root->right);
}
};
迭代版:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> a;
stack<TreeNode*> s;
TreeNode* p=root;
while(p||!s.empty())
{
while(p)
{
s.push(p);
p=p->left;
}
p=s.top();
s.pop();
a.push_back(p->val);
p=p->right;
}
return a;
}
};
注:中等题,二叉树的遍历,中序、前序、后序、层次这四个的递归和迭代版本必须烂熟于心。faster than 100.00% 。
95. Unique Binary Search Trees II
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<TreeNode*> generateTrees(int n) {
vector<TreeNode*> ret;
if(n == 0)
return ret;
return constructTree(1, n);
}
private:
vector<TreeNode*> constructTree(int start, int end){
vector<TreeNode*> subTree;
if(start > end)
subTree.push_back(NULL);
else{
for(int i = start; i <= end; i++){
vector<TreeNode*> leftSub = constructTree(start, i-1);
vector<TreeNode*> rightSub = constructTree(i+1, end);
for(int a = 0; a < leftSub.size(); a++){
for(int b = 0; b < rightSub.size(); b++){
TreeNode* root = new TreeNode(i);
root->left = leftSub[a];
root->right = rightSub[b];
subTree.push_back(root);
}
}
}
}
return subTree;
}
};
http://www.cnblogs.com/yaoyudadudu/p/9158382.html
注:中等题,好题,这题在遍历的时候我跟上行链接的作者陷入了同一个旋涡,到底该返回啥,其实可以返回vector<Tree>,其实还有动态规划的,二叉树用DP太反人类了,果断不学。faster than XX% 。
96. Unique Binary Search Trees
https://blog.csdn.net/yinchaoji_/article/details/70137002
https://blog.csdn.net/u012501459/article/details/46622501
注:中等题,。faster than XX% 。
97. Interleaving String
递归回溯(超时):
class Solution {
public:
bool isInterleave(string s1, string s2, string s3) {
int p=0,q=0;
if(s1.size()+s2.size()!=s3.size())
return false;
return digui(s1,s2,s3,p,q,0);
}
bool digui(string s1, string s2, string s3,int p,int q,int k)
{
for(int i=k;i<s3.size();i++)
{
if(p<s1.size()&&s3[i]==s1[p])
if(digui(s1,s2,s3,p+1,q,i+1))
return true;
if(q<s2.size()&&s3[i]==s2[q])
if(digui(s1,s2,s3,p,q+1,i+1))
return true;
}
return p+q==s3.size();
}
};
记忆化搜索:
class Solution {
public:
bool isInterleave(string s1, string s2, string s3) {
vector<vector<int>> a(s1.size(),vector<int>(s2.size(),-1));
if(s1.size()+s2.size()!=s3.size())
return false;
return digui(a,s1,s2,s3,0,0,0);
}
bool digui(vector<vector<int>> &a,string s1, string s2, string s3,int p,int q,int k)
{
if(p==s1.size())
return s2.substr(q)==s3.substr(k);
if(q==s2.size())
return s1.substr(p)==s3.substr(k);
if(a[p][q]!=-1)
return a[p][q];
bool c=0;
if(p<s1.size()&&s3[k]==s1[p])
if(digui(a,s1,s2,s3,p+1,q,k+1))
c=1;
if(q<s2.size()&&s3[k]==s2[q])
if(digui(a,s1,s2,s3,p,q+1,k+1))
c=1;
a[p][q]=c;
return a[p][q];
}
};
注:困难题,本题首先想到的就是递归回溯,写出来我就知道会超时,果不其然;很明显是动态规划问题,在递归回溯的时候存在着大量的重叠子问题,我只会写记忆化搜索,答案参考了solution。faster than 100.00% 。
98. Validate Binary Search Tree
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
bool isValidBST(TreeNode* root) {
return isValidBST(root, LONG_MIN, LONG_MAX);
}
bool isValidBST(TreeNode *root, long mn, long mx) {
if (!root) return true;
if (root->val <= mn || root->val >= mx) return false;
return isValidBST(root->left, mn, root->val) && isValidBST(root->right, root->val, mx);
}
};
注:中等题,利用中序遍历思想做。faster than XX% 。
99. Recover Binary Search Tree
注:困难题,利用中序遍历思想做。faster than XX% 。
100. Same Tree
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
bool isSameTree(TreeNode* p, TreeNode* q) {
if(!p&&!q)
return true;
if(!p||!q)
return false;
if(p->val==q->val)
return isSameTree(p->left,q->left)&&isSameTree(p->right,q->right);
else return false;
}
};
注:中等题,直接递归就好,看好递归条件,如果两树都为空返回true,一树为空直接返回false,然后再比较节点的值,二叉树的问题第一个想到的就应该是递归。faster than 100.00% 。
Rrui的Leetcode算法刷题笔记(三)链接如下: