Leetcode算法刷题笔记(一)

编程语言C++,部分代码参考大佬,为思路,题目标为红色为不会并附参考代码链接,黄色为可再做一遍的题目,绿色为懒得自己做或再也不想看到的题。标题页数即为算法题目出现页数。

注:LeetCode的编译器更新了,正好赶上了秋招,重新做一遍,这回注重代码质量和代码可读性。

 

1.Two Sum

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        
        int size = nums.size();
        unordered_map<int,int> dict;
        
        for(int i=0; i<size; i++)
        {
            int difference = target-nums[i];
            if(dict.find(difference)==dict.end())
                dict[nums[i]] = i;
            else return {dict[difference],i};
        }
        return {};
    }
};

注:简单题,使用map边遍历边查询即可。

Runtime: 8 ms, faster than 97.70% of C++ online submissions for Two Sum.

Memory Usage: 10.3 MB, less than 22.42% of C++ online submissions for Two Sum.

 

2. Add Two Numbers

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        
        ListNode* sum = new ListNode(0);
        ListNode* p = sum;
        int carry = 0;
        
        while(l1 || l2)
        {
            int l1_val=0, l2_val=0;
            
            if(l1)
            {
                l1_val = l1->val;                
                l1 = l1->next;
            }

            if(l2)
            {
                l2_val = l2->val;                
                l2 = l2->next;                
            }

            int add = (l1_val + l2_val + carry);
            ListNode* q = new ListNode(add%10);
            p->next = q;
            p = p->next;   
            carry = add/10;
        }
        
        if(carry)
        {
            ListNode* q = new ListNode(carry);
            p->next = q;
            p = p->next;  
        }
            
        return sum->next;
    }
};

注:中等题,链表从前到后遍历即可,只需注意一下进位,还有两个链表都遍历完以后的进位情况即可。

Runtime: 16 ms, faster than 99.35% of C++ online submissions for Add Two Numbers.

Memory Usage: 10.6 MB, less than 45.72% of C++ online submissions for Add Two Numbers.

 

3. Longest Substring Without Repeating Characters

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        
        int lenth = 0, maximum = 0;
        int left = 0, right = 0;
        unordered_map<int, int> dict;

        for(int i=0; i<s.size(); i++)
        { 
            if(dict.find(s[i])==dict.end())
            {
                dict[s[i]] = i;
                lenth++;
            }
            else
            {
                if(dict[s[i]]<left)     //如果在窗口外则无需考虑,更新value即可
                {
                    dict[s[i]] = i;
                    lenth++;
                }
                else
                {
                    right = i;
                    left = dict[s[i]];
                    dict[s[i]] = i;
                    lenth = right - left;
                }
            }
            if(lenth>maximum)
                maximum = lenth;
        }
        return maximum;
    }
};

注:中等题,滑动窗口加字典即可解决,唯一需要注意的情况就是如果字典值在窗口外就更新一下字典值就好了。

Runtime: 16 ms, faster than 80.05% of C++ online submissions for Longest Substring Without Repeating Characters.

Memory Usage: 11 MB, less than 63.42% of C++ online submissions for Longest Substring Without Repeating Characters.

 

4. Median of Two Sorted Arrays

O(n+m)版:

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        
        int a=nums1.size();
        int b=nums2.size();
        
        nums1.push_back(INT_MAX);
        nums2.push_back(INT_MAX);  
        
        int c=(a+b)%2==0?1:0;
        
        int*d=new int[a+b];
        int j=0;
        int p=0;
		for (int i = 0; i<a + b; i++)
		{
			if (nums1[j] <= nums2[p])
			{
				d[i] = nums1[j];
				j++;
			}
			else 
			{
				d[i] = nums2[p];
				p++;
			}
        }
        int k=(a+b)/2;
        if(c)
            return (double(d[k])+d[k-1])/2;
        else
            return d[k];
    }
};

O(log(n+m))版:

class Solution {
public:
    int findKSmallestSortedArrays(vector<int>::iterator l1, vector<int>::iterator r1,
                                  vector<int>::iterator l2, vector<int>::iterator r2, int k) {
      //一个数组为空时迅速结束递归
      if (l1 == r1) return *(l2 + k - 1);
      if (l2 == r2) return *(l1 + k - 1);
      //k=1,递归结束
      if (k == 1) return *l1 < *l2 ? * l1 : *l2;
      int mid1 = r1 - l1 < k / 2 ? r1 - l1 : k / 2;
      int mid2 = k - mid1;
      int val1 = *(l1 + mid1 - 1);
      int val2 = *(l2 + mid2 - 1);
      if (val1 < val2)
        return findKSmallestSortedArrays(l1 + mid1, r1, l2, r2, k - mid1);
      else
        return findKSmallestSortedArrays(l1, r1,l2 + mid2, r2, k - mid2);
    }

    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
      int size = nums1.size() + nums2.size();
      if (size == 0) return 0.0;
      if (size % 2 == 1)
        return findKSmallestSortedArrays(nums1.begin(), nums1.end(), nums2.begin(), nums2.end(), size / 2 + 1);
      else
        return (findKSmallestSortedArrays(nums1.begin(), nums1.end(), nums2.begin(), nums2.end(), size / 2)
              + findKSmallestSortedArrays(nums1.begin(), nums1.end(), nums2.begin(), nums2.end(), size / 2 + 1))
              / 2.0;
    }
};

http://www.cnblogs.com/vingo278/p/6108106.html

注:困难题,本题如不按要求,用O(n+m)复杂度也能过。faster than 30.87% 。按要求的就不会了。

5. Longest Palindromic Substring

class Solution{
public: 
    string longestPalindrome(string s)
    {
        if (s.empty()) return "";
        int len = s.size();
        if (len == 1)return s;
        int longest = 1;
        int start=0;
        vector<vector<int> > dp(len,vector<int>(len));
        for (int i = 0; i < len; i++)
        {
            dp[i][i] = 1;
            if(i<len-1)
            {
                if (s[i] == s[i + 1])
                {
                    dp[i][i + 1] = 1;
                    start=i;
                    longest=2;
                }
            }
        }
        for (int l = 3; l <= len; l++)//子串长度
        {
            for (int i = 0; i+l-1 < len; i++)//枚举子串的起始点
            {
                int j=l+i-1;//终点
                if (s[i] == s[j] && dp[i+1][j-1]==1)
                {
                    dp[i][j] = 1;
                    start=i;
                    longest = l;
                }
            }
        }
        return s.substr(start,longest);
    }
};

https://www.cnblogs.com/mini-coconut/p/9074315.html

注:困难题,动态规划算法。faster than XX% 

 

6. ZigZag Conversion

class Solution {
public:
    string convert(string s, int numRows) {
        
        string output;
        int size = s.size();
        int stride = 2*numRows-2;
        
        if(numRows ==1)
            return s;
        
        for(int i=0;i<numRows;i++)
        {
            int row = i;
            if(row==0 || row==(numRows-1))
            {
                while(row<size)
                {
                    output.push_back(s[row]);
                    row+=stride;
                }
            }
            else
            {
                while(row<size)
                {
                    output.push_back(s[row]);
                    if(row + stride - 2*i<size)
                        output.push_back(s[row + stride - 2*i]);  
                    row+=stride;
                } 
            }
        }
        return output;
    }
};

注:中等题,此类题就是找规律,这里的规律就是第一行和最后一行每个数差了2*numRows-2,中间各行每三个元素,第一个和第二个差了2*numRows-2-2*i,第一个和第三个差2*numRows-2。

Runtime: 12 ms, faster than 92.19% of C++ online submissions for ZigZag Conversion.

Memory Usage: 10.4 MB, less than 73.44% of C++ online submissions for ZigZag Conversion.

 

7. Reverse Integer

class Solution {
public:
    int reverse(int x) {
        
        long long reverse = 0;

        while(x)
        {
            reverse = reverse*10 + x%10;
            x/=10;
            
            if(reverse>INT_MAX || reverse<INT_MIN)
                return 0;
        }
        return reverse;
    }
};

注:简单题,只要把sum设置成long long型不怕越界那就不要怂,上来就是干,除余即可。

Runtime: 4 ms, faster than 89.75% of C++ online submissions for Reverse Integer.

Memory Usage: 8.3 MB, less than 54.72% of C++ online submissions for Reverse Integer.

 

8. String to Integer (atoi)

class Solution {
public:
    int myAtoi(string str) {
        
        long long result = 0;
        bool sign = true;
        int bit = 1; 
        
        for(int i=0;i<str.size();i++)
        {
            if(str[i]==' ' && sign)
                continue;
            
            if(str[i]>='0' && str[i]<='9')
            {
                sign = false;
                result = result * 10 + str[i] - '0';
                
                if(bit*result<INT_MIN)
                    return INT_MIN;
                else if(bit*result>INT_MAX)
                    return INT_MAX;
                
                continue;
            }
            
            if((str[i]=='+' || str[i]=='-') && sign)
            {
                if(str[i]=='-')
                    bit = -1;
                sign = false;
            }
            else return bit*result;
        }
        return bit*result;
    }
};

注:中等题,本身无难度,只需要注意各种特殊条件,当出现'+'或‘-’后,空格就算无效字符了 

Runtime: 8 ms, faster than 81.81% of C++ online submissions for String to Integer (atoi).

Memory Usage: 8.5 MB, less than 57.82% of C++ online submissions forString to Integer (atoi).

 

9. Palindrome Number

class Solution {
public:
    bool isPalindrome(int x) {
        
        if(x<0)
            return false;
        
        string s = to_string(x);
        reverse(s.begin(), s.end());
        
        return s==to_string(x);
    }
};

注:简单题,我用的反转字符串这样写的简单,懒得又余又除的 

Runtime: 28 ms, faster than 70.95% of C++ online submissions forPalindrome Number.

Memory Usage: 8.1 MB, less than 66.97% of C++ online submissions forPalindrome Number.

 

10. Regular Expression Matching

注:困难题,。faster than XX% 

11. Container With Most Water

class Solution {
public:
    int maxArea(vector<int>& height) {
        
        int first=0,end=height.size()-1,max1=0;
        
        while(end>first)
        {
            max1=max(min(height[end],height[first])*(end-first),max1);
            if(height[end]>height[first])
                first++;
            else end--;
        }
        return max1;
    }
};

注:中等题,使用头尾双指针,谁小谁动,直到头指针等于尾指针跳出循环,对于数组题,字典双指针滑窗动态规划,这四个一般都能用得上。。faster than 98.32% 

12. Integer to Roman

class Solution {
public:
    string intToRoman(int num) {
        // using array is faster than vector
        int nums[13] = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};  
        string roman[13] = {"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"};  
        int k = 0;  
        string result;  
        while(num > 0)  
        {  
            if(num >= nums[k])  
                result += roman[k], num -= nums[k];  
            else 
                k++;  
        }  
        return result;  
    }
};

注:中等题,这题直接就干,没啥想说的,想再做一遍是因为语法的问题。faster than 96.06% 

13. Roman to Integer

class Solution {
public:
    int romanToInt(string s) {

        int k=0;
        unordered_map<char, int> a = {{'I', 1}, {'V', 5}, {'X', 10}, {'L', 50}, {'C', 100}, {'D', 500}, {'M', 1000}};
        
        for(int i=0;i<s.size();i++)
        {
            if(i+1<s.size()&&a[s[i]]<a[s[i+1]]) 
                k=k+a[s[i+1]]-a[s[i++]];
            else k+=a[s[i]];
        }
        return k;
    }
};

注:简单题,就看一下下一个字符是否大于当前字符就可以了,这里学会了一个新的哈希表初始化方法。faster than 58.75% 

14. Longest Common Prefix

class Solution {
public:
    string longestCommonPrefix(vector<string>& strs) {
        
        string output;
        
        if(strs.size()==0)
            return output;
        
        for(int i=0;i<strs[0].size();i++)
        {
            char prefix = strs[0][i];
            for(int j=1;j<strs.size();j++)
            {
                if(i>=strs[j].size() || strs[j][i]!=prefix)
                    return output;
            }
            output.push_back(prefix);
        }
        return output;
    }
};

注:简单题,拿出第一个字符串,然后挨个遍历跟第一个对比记录公共前缀个数即可,注意特殊输入还有个[]。

Runtime: 4 ms, faster than 98.38% of C++ online submissions for Longest Common Prefix.

Memory Usage: 8.9 MB, less than 63.49% of C++ online submissions forLongest Common Prefix.

 

15. 3Sum

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        
        vector<vector<int>> output;
        sort(nums.begin(), nums.end());
        
        for(int i=0;i<nums.size();i++)
        {
            int target = -nums[i];
            int left = i+1, right = nums.size()-1;
                
            if(i-1>=0 && nums[i-1]==nums[i])
                continue;        
                        
            while(left<right)     
            {
                if(nums[left]+nums[right]==target)
                {
                    output.push_back(vector<int>{nums[i], nums[left], nums[right]});

                    while(left<right && nums[left]==nums[++left]);
                    while(left<right && nums[right]==nums[--right]);           
                }
                else if(nums[left]+nums[right]<target)
                    left++;
                else right--;
            } 
        }
        return output;
    }
};

注:中等题,用map键值去重时间很慢而且容易超时,本体内循环使用双指针,这样能加速。

Runtime: 88 ms, faster than 99.46% of C++ online submissions for 3Sum.

Memory Usage: 14.9 MB, less than 71.15% of C++ online submissions for3Sum.

 

16. 3Sum Closest

class Solution {
public:
    int threeSumClosest(vector<int>& nums, int target) {
        
        sort(nums.begin(),nums.end());
        int gap=INT_MAX,val=target;
        for(int i=0;i<nums.size()-2;i++)
        {
            int first=i+1,end=nums.size()-1,sum=target-nums[i];
            while(end>first)
            {
                int gap1=min(gap,abs(sum-nums[end]-nums[first]));
                val=gap1==gap?val:nums[i]+nums[end]+nums[first];
                gap=gap1;
                if(nums[end]+nums[first]<sum)
                    first++;
                else end--;
            }
        }
        return val;
    }
};

注:中等题,与第15题思路完全一样,就是判断谁的和与target的距离最小了,还是排序后应用双指针。faster than 65.40% 

 

17. Letter Combinations of a Phone Number

class Solution {
public:
    vector<string> letterCombinations(string digits) {
        
        vector<string> output;
        string s;
        unordered_map<int,vector<char>> dict;
        
        if(digits.size()==0)
            return output;
        
        for(int i=0;i<5;i++)
        {
            
            dict[i+2] = {'a'+3*i, 'b'+3*i, 'c'+3*i};
        }
        dict[7] = {'p', 'q', 'r', 's'};
        dict[8] = {'t', 'u', 'v'};
        dict[9] = {'w', 'x', 'y', 'z'};
        
        recurrent(dict, output, digits, s, 0);
        return output;
    }
    
    void recurrent(unordered_map<int,vector<char>>& dict, vector<string>& output ,string digits ,string s ,int k)
    {
        if(k==digits.size())
        {
            output.push_back(s);
            return ;
        }
        
        for(int i=0;i<dict[digits[k]-'0'].size();i++)
        {
            s.push_back(dict[digits[k]-'0'][i]);
            recurrent(dict, output, digits, s, k+1);
            s.pop_back();
        }        
        
    }
};

注:中等题,典型的回溯算法求解。

Runtime: 4 ms, faster than 87.66% of C++ online submissions for Letter Combinations of a Phone Number.

Memory Usage: 8.6 MB, less than 55.52% of C++ online submissions forLetter Combinations of a Phone Number.

 

18. 4Sum

class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        
        vector<vector<int>> a;
        
        if(nums.size()<4)
            return a;
        sort(nums.begin(),nums.end());
        
        for(int i=0;i<nums.size()-3;i++)
        {
            if(i-1>=0&&nums[i-1]==nums[i])
                continue;
            for(int j=i+1;j<nums.size()-2;j++)
            {
                if(j-1>=i+1&&nums[j-1]==nums[j])
                    continue; 
                int first=j+1,end=nums.size()-1,sum=target-nums[i]-nums[j];
                while(end>first)
                {
                    if(nums[end]+nums[first]==sum)
                    {
                        a.push_back({nums[i],nums[j],nums[end],nums[first]});                                       while(nums[end]==nums[--end]);
                    }
                    else if(nums[end]+nums[first]<sum)
                        first++;
                    else end--;
                }
            }
        }
        return a;
    }
};

注:中等题,与第15题思路一样,就是多了个循环而已。faster than 89.62% 

 

 

19. Remove Nth Node From End of List

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        
        if(!head)
            return head;
        
        ListNode* left = head;
        ListNode* right = head;        
        
        while(n--)
            right = right->next;
        
        if(!right)
            return head->next;
        
        while(right->next)
        {
            right = right->next;
            left = left->next;
        }
    
        left->next = left->next->next; 
        return head;
    }
};

注:中等题,应用了快慢指针(双指针)的思想,快指针比慢指针多走了n步,那么当快指针的下一节点为空时,慢指针的下一节点正好为head指针的倒数第n个节点。

Runtime: 0 ms, faster than 100.00% of C++ online submissions for Remove Nth Node From End of List.

Memory Usage: 8.5 MB, less than 82.14% of C++ online submissions forRemove Nth Node From End of List.

 

20. Valid Parentheses

class Solution {
public:
    bool isValid(string s) {
        
        stack<char> Parentheses;
        
        for(char input :s)
        {
            if(Parentheses.size()==0)
            {
                Parentheses.push(input);
                continue;
            }
            if((Parentheses.top()=='(' && input==')') || (Parentheses.top()=='[' && input==']') || (Parentheses.top()=='{' && input=='}'))
                Parentheses.pop();
            else 
                Parentheses.push(input);
        }
        return !Parentheses.size();
    }
};

注:简单题,利用栈即可,判断栈顶是否与当前char匹配,如果匹配就弹出,不匹配就把char压入栈,,如果最后栈为空则true,否则为false。

Runtime: 4 ms, faster than 87.59% of C++ online submissions for Valid Parentheses.

Memory Usage: 8.7 MB, less than 44.07% of C++ online submissions forValid Parentheses.

 

21. Merge Two Sorted Lists

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        
        ListNode* m = new ListNode(0);
        ListNode* p = m;
        int val;
        
        while(l1 || l2)
        {
            if(!l1)
            {
                p->next = l2;
                break;
            }
                
            if(!l2)
            {
                p->next = l1;
                break;
            }
            

            if(l1->val>l2->val)
            {
                val = l2->val;
                l2 = l2->next;
            }   
            else
            {
                val = l1->val;
                l1 = l1->next;
            }
            
            ListNode* q = new ListNode(val);            
            p->next = q;
            p = p->next;
        }
        return m->next;
    }
};

注:简单题,两个链表节点挨个比较即可,谁的小就把谁接到输出链表上,当遍历完其中一个链表就把另一个链表的剩余部分拼接到输出链表上就好了。

Runtime: 8 ms, faster than 92.93% of C++ online submissions for Merge Two Sorted Lists.

Memory Usage: 9.2 MB, less than 43.65% of C++ online submissions for Merge Two Sorted Lists.

 

22. Generate Parentheses

class Solution {
public:
    vector<string> generateParenthesis(int n) {
        vector<string> result;
        string s;
        if(n > 0)
        {
            generateParenthesisHelper(result, s, n, 0, 0, 0);
        }
        return result;
    }
    void generateParenthesisHelper(vector<string>& result, string &s, int n, int deep, int left, int right)
    {
        if(deep == 2*n)
        {
            result.push_back(s);
            return;
        }
        if(left < n)
        {
            s.push_back('(');
            generateParenthesisHelper(result, s, n, deep + 1, left + 1, right);
            s.resize(s.size() - 1);
        }
        if(right < left)
        {
            s.push_back(')');
            generateParenthesisHelper(result, s, n, deep + 1, left, right +1);
            s.resize(s.size() - 1);
} } };

https://www.cnblogs.com/jingyuewutong/p/5583201.html

注:中等题,递归条件不熟悉。faster than XX% 

23. Merge k Sorted Lists

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        
        if(lists.size()==0)
            return NULL;
        ListNode* p=lists[0];

        for(int i=1;i<lists.size();i++)
        {
            bool b=false,c=false;
            ListNode* m=new ListNode(0);
            ListNode* q=m;
            while(!b||!c)
            {
                if(c||p&&lists[i]&&p->val<lists[i]->val)
                {
                    if(!p)
                    {
                        b=true;                        
                        continue;                        
                    }
                    q->next=p;
                    p=p->next;
                    if(!p)
                        b=true;
                }
                else if(!c)
                {
                    if(!lists[i])
                    {
                        c=true;                        
                        continue;
                    }
                    q->next=lists[i];
                    lists[i]=lists[i]->next;                    
                    if(!lists[i])
                        c=true;
                }
                q=q->next;
            }
            p=m->next;
        }
        return p;
    }
};

注:困难题,编程序不能循规蹈矩,否则就会像我这个程序一样,真就是一个个链表进行比较,编程序中还得注意各种空链表,空指针,可能是做其他的链表题形成的惯性思维。。这题最简单的思路就是把所有节点的值都保存下来,然后排个序再恢复成链表,考验智商的一道题,我失败了。。。faster than 13.59% 

 

24. Swap Nodes in Pairs

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        
        if(!head || !head->next)
            return head;
        
        ListNode* m = new ListNode(0);
        ListNode* r = m;

        while(head && head->next)
        {
            ListNode* p = head->next->next;
            ListNode* q = head->next;
            head->next = NULL;
            q->next = NULL;
            q->next = head;
            head->next = p;
            r->next = q;
            r = r->next->next;
            head = head->next;
        }
        return m->next;
    }
};

注:中等题,交换链表节点和反转链表等都是链表的基本操作,一般的做法都是定义三个指针分别指向当前节点,当前节点的下个节点还有下下个节点,本题需要注意奇偶个数节点操作的不同。我比较喜欢这种三指针法,简单明了。

Runtime: 4 ms, faster than 90.29% of C++ online submissions for Swap Nodes in Pairs.

Memory Usage: 8.8 MB, less than 37.71% of C++ online submissions for Swap Nodes in Pairs.

 

25. Reverse Nodes in k-Group

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *reverseKGroup(ListNode *head, int k) {
        
        if(k<=1)
            return head;
        
        ListNode *m = new ListNode(0);
        ListNode *p = m;
        while(head)
        {
            int sum = k-1;
            
            ListNode *q = head;
            while(q && sum)
            {
                --sum;
                q = q->next;
            }
            if(sum || !q)
                break;
            
            ListNode *cache = q->next;
            q->next = nullptr;
            p->next = reverse(head);
            while(sum!=k)
            {
                ++sum;
                p = p->next;
            }
            head = cache;
        }
        p->next = head;
        return m->next;
    }
    
    ListNode *reverse(ListNode *head) {
        
        ListNode *p = nullptr;
        ListNode *q = head;
        
        while(q)
        {
            ListNode *r = q->next;
            q->next = p;
            p = q;
            q = r;
        }
        return p;
    }
};

注:困难题,与24题相似,反转链表的另一题型,此题思路并不难想到,首先选择K个节点为一个链表,然后断开其后继,对这个链表进行反转,反转完毕后接回去就好了.

Runtime: 20 ms, faster than 91.34% of C++ online submissions for Reverse Nodes in k-Group.

Memory Usage: 9.8 MB, less than 69.14% of C++ online submissions for Reverse Nodes in k-Group.

 

26. Remove Duplicates from Sorted Array

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        
        if(nums.size()==0)
            return 0;
        
        sort(nums.begin(), nums.end());
        int left = 1;
        
        for(int i=1;i<nums.size();i++)
        {
            if(nums[i]!=nums[i-1])
                nums[left++] = nums[i];
        }
        return left;
    }
};

注:简单题,使用指针left指向需保留的数组,如有非重复数字则替换j指向的当前数据并且left++。

Runtime: 24 ms, faster than 85.71% of C++ online submissions for Remove Duplicates from Sorted Array.

Memory Usage: 9.9 MB, less than 60.31% of C++ online submissions forRemove Duplicates from Sorted Array.

 

27. Remove Element

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        
        int left = 0;
        
        for(int i=0;i<nums.size();i++)
        {
            if(nums[i]!=val)
                nums[left++]=nums[i];
        }
        return left;
    }
};

注:简单题,跟26一样的思路,遍历一遍就可以了

Runtime: 0 ms, faster than 100.00% of C++ online submissions for Remove Element.

Memory Usage: 8.7 MB, less than 52.17% of C++ online submissions forRemove Element.

 

28. Implement strStr()

class Solution {
public:
    int strStr(string haystack, string needle) {
        
        int needle_size = needle.size();
        
        if(needle_size>haystack.size())
            return -1;
        
        if(needle_size==0)
            return 0;
        
        for(int i=0;i+needle_size<=haystack.size();i++)
        {
            if(haystack.substr(i, needle_size)==needle) 
                return i;
        }
        return -1;
    }
};

注:简单题,使用string的substr函数当滑窗从前到后遍历一遍就好了。faster than 98.60% 

Runtime: 8 ms, faster than 71.16% of C++ online submissions forImplement strStr().

Memory Usage: 9.4 MB, less than 40.01% of C++ online submissions forImplement strStr().

 

29. Divide Two Integers

class Solution {
public:
    const int M = (int)(pow(2,31)-1), m = -M-1;
    int divide(int dividend, int divisor) {
        if (dividend == m && divisor == -1) return M;
        int f = 0, ans = 0, T = divisor, t;
        if (dividend > 0) dividend = -dividend, f ^= 1;
        if (divisor > 0) divisor = -divisor, f ^= 1;
        while (divisor >= dividend)
        {
            t = -1, T = divisor;
            while ((T << 1)<0 && (T << 1) >= dividend) T <<= 1, t <<= 1;
            if (f) ans += t;
            else ans -= t;
            dividend -= T;
        }
        return ans;
    }
};

https://blog.csdn.net/s1293678392/article/details/80537231

注:中等题,边界调减变态的不解释。faster than XX% 

30. Substring with Concatenation of All Words

class Solution {
public:
    vector<int> findSubstring(string s, vector<string>& words) {
        
        unordered_map<string,int> c;
        vector<int> b;
        if(words.size()==0)
            return b;
        
        int left=0,right=0,size=words[0].size(),p=0,count=0,_left=0;
        
        for(int i=0;i<words.size();i++)
        {
            if(words[i].size()!=size)
                return b;
            c[words[i]]++;
        }
        unordered_map<string,int> a{c};    
        while(right<s.size())
        {
            right+=size;
            if(a.find(s.substr(right-size,size))==a.end())
            {
                left++;
                _left=left;
                right=left;
                count=0;
                a=c;
            }
            else
            {
                a.find(s.substr(right-size,size))->second--;
                if(a.find(s.substr(right-size,size))->second>=p)
                    count++;
                else
                {
                    while(a.find(s.substr(right-size,size))->second<p)
                    {
                        a.find(s.substr(_left,size))->second++;
                        _left+=size;
                        count--;
                    }
                    count++;
                }
                if(count==words.size())
                {
                    if(b.empty()||!b.empty()&&_left!=b.back())
                        b.push_back(_left);
                    left++;
                    _left=left;
                    right=left;
                    count=0;
                    a=c;
                }
            }
        }
        return b;
    }
};

注:困难题,就这道题描述跟我说的不明不白的,害得我之前搭好的程序框架变成了一锅粥,操。faster than 13.05% 

31. Next Permutation

class Solution {
public:
    void nextPermutation(vector<int>& 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());
        }
    }
};

注:中等题,这规律给我一年也想不出来。faster than XX% 

32. Longest Valid Parentheses

 

注:困难题,。faster than XX% 

33. Search in Rotated Sorted Array

class Solution {
public:
    int search(vector<int>& nums, int target) {
        if(nums.size() == 0)
            return -1;
        int left = 0;
        int right = nums.size() - 1;
        while(left <= right){
            int mid = (left + right)/2;
            if(nums[mid] == target)
                return mid;
            else if(nums[mid] < nums[right]){
                if(nums[mid] < target && target <= nums[right]){
                    left = mid + 1;
                }else{
                    right = mid - 1;
                }
            }else{
                if(nums[left] <= target && nums[mid] > target)
                    right = mid-1;
                else
                    left = mid + 1;
            }
        }
        return -1;
    }
};

注:中等题,考察二分法的变体,主要找有序区间,没做出来钻牛角尖了。。faster than XX% 

34. Find First and Last Position of Element in Sorted Array

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        
        int low=0,high=nums.size()-1;
        vector<int> a(2,-1);
        if(nums.size()==0)
            return a;
               
        while(high>=low)
        {
            int mid=(low+high)/2;
            if(nums[mid]<target)
                low=mid+1;
            else high=mid-1;
        }
        
        if(low>nums.size()-1||nums[low]!=target)
            return a;
        else a[0]=low;
        
        low=0,high=nums.size()-1;
        
        while(high>=low)
        {
            int mid=(low+high)/2;
            if(nums[mid]>target)
                high=mid-1;
            else low=mid+1;
        }        
        
        if(a[0]==-1)
            return a;
        else a[1]=high;        
        
        return a; 
    }
};

注:中等题,考察二分法的两种应用,第一个出现和最后出现的位置,两次二分法就好了,时间复杂度O(nlog(n))。faster than 100.00% 

 

35. Search Insert Position

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        
        int left = 0, right = nums.size();
        
        while(left<right)
        {
            long long middle = (left + right)/2;
            if(nums[middle]<target)
                left = middle + 1;
            else if(nums[middle]>target)
                right = middle;
            else return middle;
        }
        return left;
    }
};

注:简单题,二分法的典型应用,时间复杂度O(nlog(n))。

Runtime: 4 ms, faster than 99.56% of C++ online submissions for Search Insert Position.

Memory Usage: 8.9 MB, less than 55.32% of C++ online submissions forSearch Insert Position.

 

36. Valid Sudoku

class Solution {
public:
    bool isValidSudoku(vector<vector<char>>& board) {
        if (board.empty())
            return false;

        //数独游戏符合9宫格,也就是为一个9*9的矩阵
        int size = board.size();

        //根据数独游戏的规则,需要进行三次检验(按行、按列、按照3*3块)
        //利用哈希的思想,记录每个关键字的出现次数,若是次数>1,则返回false
        vector<int> count;
        for (int i = 0; i < size; ++i)
        {
            //每行开始前,将记录次数的vector清零,元素1~9分别对应下标0~8,对应vector中值为该元素的出现次数
            count.assign(9, 0);
            for (int j = 0; j < size; j++)
            {
                if (board[i][j] != '.')
                {
                    int pos = board[i][j] - '1';                    
                    if (count[pos] > 0)
                        return false;
                    else
                        ++count[pos];
                }
                else
                    continue;

            }//for
        }//for

        //同理,按列检验
        for (int j = 0; j < size; j++)
        {
            count.assign(9, 0);
            for (int i = 0; i < size; i++)
            {
                if (board[i][j] != '.')
                {
                    int pos = board[i][j] - '1';

                    if (count[pos] > 0)
                        return false;
                    else
                        ++count[pos];;
                }
                else
                    continue;
            }//for
        }//for

        //按3*3小块检验
        for (int i = 0; i < size; i += 3)
        {           
            for (int j = 0; j < size; j += 3)
            {
                count.assign(9, 0);
                //每个块又是一个3*3的矩阵
                for (int row = i; row < i + 3;row++)
                for (int col = j; col < j + 3; col++)
                {
                    if (board[row][col] != '.')
                    {
                        int pos = board[row][col] - '1';
                        if (count[pos] > 0)
                            return false;
                        else
                            ++count[pos];;
                    }
                    else
                        continue;
                }
            }//for
        }//for

        return true;
    } 
};

https://blog.csdn.net/fly_yr/article/details/47983109

注:中等题,懒得自己做,各种循环就好了。faster than XX% 

37. Sudoku Solver

 

注:困难题,。faster than XX% 

 

38. Count and Say

class Solution {
public:
    string countAndSay(int n) {
        
        string output;
        string cache;
        cache.push_back('1');
        
        for(int i=0;i<n-1;i++)        
        {
            int num =1;
            for(int j=1;j<cache.size();j++)
            {
                if(cache[j]==cache[j-1])
                    num++;
                else
                {
                    output+=to_string(num);
                    output+=cache[j-1];
                    num = 1;
                }  
            }
            output+=to_string(num);
            output+=cache[cache.size()-1];        
            cache = output;
            output.clear();
        }
        return cache;
    }
};

注:简单题,定义第一个字符串为“1”然后慢慢数就行了。

Runtime: 0 ms, faster than 100.00% of C++ online submissions for Count and Say.

Memory Usage: 8.7 MB, less than 81.25% of C++ online submissions for Count and Say.

 

 

 

39. Combination Sum

class Solution {
public:
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        
        vector<vector<int>> a;
        vector<int> b;
         
        digui(candidates,a,b,target,0);
        return a; 
    }
    
    void digui(vector<int>& candidates, vector<vector<int>> &a,vector<int> b,int target,int k)
    {
        if(target<=0)
        {
            if(target==0)             
                a.push_back(b);                
            return ;
        }
        
        for(int i=k;i<candidates.size();i++)
        {
            b.push_back(candidates[i]);
            digui(candidates,a,b,target-candidates[i],i);
            b.pop_back();
        }
    }
};

注:中等题,如果不要求去重那就是递归就可以解的简单题,本题重点在于去重,我的思路就是第i个数用过后它的递归函数中for循环也从i点开始循环,忽略前面的数,这样就可以保证不重复了,所以引入了int k,比我快的跟我思路一样,代码就一点点不一样,不知道为啥能差了4ms。faster than 60.73% 

40. Combination Sum II

class Solution {
public:
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {

        vector<vector<int>> a;
        vector<int> b;
        sort(candidates.begin(),candidates.end());          
        digui(candidates,a,b,target,0);
        return a; 
    }
    
    void digui(vector<int>& candidates, vector<vector<int>> &a,vector<int> b,int target,int k)
    {
        if(target<=0)
        {
            if(target==0)             
                a.push_back(b);                
            return ;
        }
        
        for(int i=k;i<candidates.size();i++)
        {
            if(i-1>=k&&candidates[i]==candidates[i-1])
                continue;
            b.push_back(candidates[i]);
            digui(candidates,a,b,target-candidates[i],i+1);
            b.pop_back();
        }
    }
};

注:中等题,同39题,重点还是去重,由于原数组内有重复元素,所以递归前先排序,本题是一个元素只能用一次,所以39题的k变为i+1,同时由于重复元素是挨着的,所以用一个就行,所以判断一下,注意一下if语句中也用到k作为边界条件。比我快的跟我思路一样,还是差了4ms。faster than39.39% 

41. First Missing Positive

class Solution {
public:
    int firstMissingPositive(vector<int>& nums) {
        
        int n = nums.size();
        // put the element to the right place
        // i must be increased from 0 to n, becasue we need to satisfy the lower number first
        for(int i=0; i<n; i++){
            while(nums[i] > 0 && nums[i] <= n && nums[nums[i]-1] != nums[i]){
                // note: nums[nums[i]-1] != nums[i] indicate the place nums[nums[i]-1] hasn't satisfied
                // so we can place the nums[i] to nums[nums[i]-1]
                swap(nums[i], nums[nums[i]-1]);
            }
        }

        // find the first missing positive
        for(int i=0; i<n; i++){
            if(nums[i] != (i+1))
                return i+1;
        }

        return n + 1;
    }
};

注:困难题。faster than XX% 

http://www.cnblogs.com/fanling999/p/7861119.html

https://www.cnblogs.com/clnchanpin/p/6727065.html

42. Trapping Rain Water

 

注:困难题。faster than XX% 

43. Multiply Strings

class Solution {
public:
    string multiply(string num1, string num2) {
        if(num1.empty()||num2.empty())
            return "0";
        string s,q="0";
        int size=num1.size();
        for(int i=num1.size()-1;i>=0;i--)
        {
            int a=num1[i]-'0',k=0;
            for(int j=num2.size()-1;j>=0;j--)
            {
                int b=num2[j]-'0';
                int c=a*b+k;
                k=c/10;
                s+=to_string(c%10);                
            }
            if(k)
                s+=to_string(k); 
            reverse(s.begin(),s.end());
            int p=size-1-i;
            while(p--)
                s+="0";
            q=add(s,q);
            s.clear();
        }
        while(q[0]=='0'&&q.size()>1)
            q.erase(q.begin());
        return q;
    }
    
    string add(string num1, string num2){
        string s;
        int k=0,i=1;
        int size1=num1.size(),size2=num2.size();
        while(size1-i>=0||size2-i>=0)
        {
            int a=0,b=0,c=0;
            if(size1-i>=0)
                a=num1[size1-i]-'0';
            if(size2-i>=0)
                b=num2[size2-i]-'0';
            c=a+b+k;
            k=c/10;
            s+=to_string(c%10);
            i++;
        }
        if(k)
           s+=to_string(k); 
        reverse(s.begin(),s.end());
        return s;
    }
};

注:中等题,烂代码,额外引入了一个函数还得遍历一次字符串,可以原地修改字符串来编写,这样最快。faster than 3.40% 

44. Wildcard Matching

class Solution {
public:
    bool isMatch(string s, string p) {

        return digui(s,p,0,0);
    }
    
    bool digui(string s,string p,int n,int k)
    {   
        if (n==s.size() && k==p.size() ) return true;
   		if (n==s.size())
		{
			bool flag = true;
			int n = p.size();
			while (k<n)
			{
				flag &= (p[k] == '*');
				k++;
			}
			return flag;
		}

		if (n==s.size() || k==p.size()) return false;
        
        for(int i=n;i<s.size();i++)
        {
            if(s[i]==p[k]||p[k]=='?')
            {
                k++;
                continue;
            } 
            else
            {
                if(p[k]=='*')
                {
                    for(int j=i;j<s.size();j++)
                        if(digui(s,p,j,k+1))
                            return true;
                }
                else return false;
            }
        }
        bool flag = true;
        while (k<p.size())
        {
            flag &= (p[k] == '*');
            k++;
        }
        return flag;
    }
};

discuss代码:

class Solution {
public:
	bool isMatch(string s, string p) {
		if (s.size() == 0 && p.size() == 0) return true;
   		if (s.size() == 0)
		{
			bool flag = true;
			int n = p.size();
			while (n > 0)
			{
				flag &= (p[n - 1] == '*');
				n--;
			}
			return flag;
		}

		if (s.size() == 0 || p.size() == 0) return false;

		for (int i = 0; i < p.size(); i++)
		{
			if (p[i] == s[i])
			{
				return isMatch(s.substr(i + 1), p.substr(i + 1));
			}
			else if (p[i] == '?')
			{
				return isMatch(s.substr(i + 1), p.substr(i + 1));
			}
			else if (p[i] == '*')
			{
				bool flag = false;
				for (int j = 0; j <= s.size(); j++)
				{
					flag = isMatch(s.substr(j), p.substr(i + 1));
					if (flag == true) break;
				}
				return flag;
			}
			else
			{
				return false;
			}
		}

		return false;
	}
};

https://blog.csdn.net/makuiyu/article/details/43698963

注:困难题。想到用回溯法了,但还是码的太费劲,超时,动态规划的不会。。faster than XX% 

45. Jump Game II

大神代码:

https://blog.csdn.net/feliciafay/article/details/42779827

我的超时代码:

class Solution {
public:
    int jump(vector<int>& nums) {
        
        vector<int> a(nums.size(),INT_MAX);
        
        for(int i=nums.size()-1;i>=0;i--)
        {
            if(i==nums.size()-1)
            {
                a[i]=0;
                continue;
            }
            for(int j=nums[i];j>=0;j--)
            {
                if(i+j>=nums.size()-1)
                {
                    a[i]=1;
                    break;
                }
                if(a[i+j]!=INT_MAX)
                    a[i]=min(a[i],1+a[i+j]);
            }
        }        
        return a[0]; 
    }
};

注:困难题,不会。faster than XX% 

 

46. Permutations

class Solution {
public:
    vector<vector<int>> permute(vector<int>& nums) {
        
        vector<vector<int>> output;
        vector<int> cache;
        
        permutation(nums, output, cache, 0);
        return output;
    }
    
    void permutation(vector<int>& nums, vector<vector<int>> &output, vector<int> cache, int k)
    {
        if(k==nums.size())
        {
            output.push_back(cache);
            return;
        }
        
        for(int i=k;i<nums.size();i++)
        {
            swap(nums[i], nums[k]);
            cache.push_back(nums[k]);
            permutation(nums, output, cache, k+1);
            cache.pop_back();
            swap(nums[i], nums[k]);
        }        
    }
};

注:中等题,让求全排列,最容易想到的就是递归,定义一个指针k指向数组的一个位置,然后for循环交换以达到排列的目的。

Runtime: 12 ms, faster than 82.46% of C++ online submissions forPermutations.

Memory Usage: 10 MB, less than 17.03% of C++ online submissions forPermutations.

 

47. Permutations II

class Solution {
public:
    vector<vector<int>> permuteUnique(vector<int>& nums) {
        
        vector<vector<int>> a;
        sort(nums.begin(),nums.end());
        digui(nums,a,0); 
        return a;
    }
    
    void digui(vector<int> nums,vector<vector<int>> &a,int k)
    {
        if(k==nums.size())
        {
            a.push_back(nums);
            return ;
        }
        for(int i=k;i<nums.size();i++)
        {
            if(nums[i]==nums[k]&&i!=k)
                continue;
            swap(nums[i],nums[k]);
            digui(nums,a,k+1);
        }
    } 
};

注:中等题,基本思想就相当于拿一个数放在最前面然后开始递归。

 

48. Rotate Image

class Solution {
public:
    void rotate(vector<vector<int>>& matrix) {
        
        for(int i=0;i<matrix.size();i++)
            for(int j=0;j<matrix.size()-i;j++)
                swap(matrix[i][j],matrix[matrix.size()-1-j][matrix.size()-1-i]);

        for(int i=0;i<matrix.size()/2;i++)
            swap(matrix[i],matrix[matrix.size()-1-i]);
    }
};

注:中等题,找规律就行了,沿对角线对称后上下翻转。faster than 70.54% 

 

49. Group Anagrams

class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        
        vector<vector<string>> output;
        unordered_map<string, int> dict;
        int num = 0;
        
        for(int i=0;i<strs.size();i++)
        {
            string sorted = strs[i];
            sort(sorted.begin(), sorted.end());
            
            if(dict.find(sorted)==dict.end())
            {
                output.push_back(vector<string>{strs[i]});
                dict[sorted] = num++;
            }
            else
                output[dict[sorted]].push_back(strs[i]);
        }
        
        return output;
    }
};

注:中等题,考察字典的一道题,遍历一遍数组使用map来储存排序后相同的原字符串即可,时间复杂度O(n),其实更为优化还可以直接把map的键值设为string,这样就不用再查找了。

Runtime: 44 ms, faster than 78.02% of C++ online submissions for Group Anagrams.

Memory Usage: 17.6 MB, less than 92.74% of C++ online submissions forGroup Anagrams.

 

50. Pow(x, n)

class Solution {
public:
    double myPow(double x, int n) {
        
        if(n==0)
            return 1;
        if(n==1)
            return x;
        
        double result = myPow(x, n/2);
        
        if(n%2==0)
            return result * result ;
        else if(n>0)
            return result * result* x;
        else return result * result /x;
    }
};
class Solution {
public:
    double myPow(double x, int n) {
        
        if(n<0)
        {
            x = 1/x;
            if(n==INT_MIN)
                return Pow(x,abs(n+1)) * x;
            else return Pow(x,abs(n));
                
        }
        else return Pow(x,n);    
        
    }
    
    double Pow(double x, int n)
    {
        if(n==1)
            return x;
        if(n==0)
            return 1;
        double result = myPow(x,n/2);
        
        result *= result;
        if(n%2)
            result *= x; 
        
        return result;  
    }
};

注:中等题,典型的二分递归法。

Runtime: 4 ms, faster than 87.52% of C++ online submissions for Pow(x, n).

Memory Usage: 8.4 MB, less than 55.58% of C++ online submissions for Pow(x, n).

 

Rrui的Leetcode算法刷题笔记(二)链接如下:

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值