Leetcode算法刷题笔记(二)

本页开始出现大量的动态规划中等题,我对自己的要求就是中等难度的会做就好,困难的就随缘吧。

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算法刷题笔记(三)链接如下:

https://blog.csdn.net/Rrui7739/article/details/82909872

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值