当前位置 博文首页 > DL_fan的博客:leetcode hot100(第一部分) + python(c++)

    DL_fan的博客:leetcode hot100(第一部分) + python(c++)

    作者:[db:作者] 时间:2021-06-25 09:28

    1-1.两数之和

    思路1:两层for循环 O(n2)

    
    class Solution:
        def twoSum(self, nums, target):
            res = []
            for i in range(len(nums)):
                for j in range(i+1, len(nums)):
                    if nums[i]+nums[j]==target:
                        res.extend([i, j])
                        break
            print('==res:', res)
            return res
    nums = [2, 7, 6, 15]
    target = 9
    sol = Solution()
    sol.twoSum(nums, target)

    思路2:hash

    python代码

    
    class Solution:
        def twoSum(self, nums, target):
            res_dict = {}
            for i in range(len(nums)):
                value = target - nums[i]
                if value in res_dict:
                    return [res_dict[value], i]
                res_dict[nums[i]] = i
                print('==res_dict:', res_dict)
            return [-1, -1]
    
    
    nums = [2, 7, 6, 15]
    target = 9
    sol = Solution()
    res = sol.twoSum(nums, target)
    print('res:', res)

    思路2:c++代码:

    #include <string>
    #include <iostream>
    #include <vector>
    #include <list>
    #include <map>
    #include <typeinfo>
    
    using namespace std;
    
    class Solution {
    public:
        vector<int> twoSum(vector<int>& nums, int target) {
            map<int, int> dict_;
            for(int k=0;k<nums.size();k++)
            {
                dict_[nums[k]] = k;
            }
            map <int,int>::iterator iter = dict_.begin();
            for (;iter!=dict_.end();iter++)
            {
                if(dict_[target - iter->first])
                {
                    // cout<<iter->second<<dict_[target - iter->first]<<endl;
                    return {iter->first,target - iter->first};
                }
            }
            return {-1,-1};
    
        }
    };
    
    int main()
    {   
        vector<int> nums;
        nums = {2,7,11,15};
        int target = 9;
        // nums = [2,7,11,15]
        Solution sol;
        vector<int> res;
        res = sol.twoSum(nums,target);
        for(int k=0;k<res.size();k++)
        {
            cout<<"==res[k]:"<<res[k]<<endl;
        }    
        return 0;
    }

    1-2,两数之和 II - 输入有序数组

    方法1:利用字典

    class Solution:
        def twoSum(self, numbers: List[int], target: int) -> List[int]:
            res_dict = {}
            for i in range(len(numbers)):
                value = target - numbers[i]
                if value in res_dict:
                    return [res_dict[value]+1, i+1]
                res_dict[numbers[i]] = i

    方法2:双指针

    
    class Solution:
        def twoSum(self, numbers, target):
            left=0
            right = len(numbers)-1
            while left<right:
                sum_= numbers[left]+numbers[right]
                if sum_==target:
                    return [left+1, right+1]
                elif sum_<target:
                    left+=1
                else:
                    right-=1
            return [-1, -1]
    
    sol = Solution()
    numbers = [2, 7, 11, 15]
    target = 9
    res = sol.twoSum(numbers,target)
    print('res:',res)
    

    2.两数相加?

    思路:开出一个head头,利用一个指针进行遍历,需要注意的是进位

    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, val=0, next=None):
    #         self.val = val
    #         self.next = next
    class Solution:
        def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
            head = ListNode(0)
            new_node = head
            carry = 0
            while l1 and l2:
                new_node.next =ListNode(l1.val+l2.val+carry)
                carry = new_node.next.val//10 
                new_node.next.val = new_node.next.val%10
                l1 = l1.next
                l2= l2.next
                new_node = new_node.next
            # print(carry)
            while l1:
                new_node.next = ListNode(l1.val+carry)
                carry  = new_node.next.val//10
                new_node.next.val = new_node.next.val%10
                l1 = l1.next
                new_node = new_node.next
            while l2:
                new_node.next =  ListNode(l2.val+carry)
                carry  = new_node.next.val//10
                new_node.next.val = new_node.next.val%10
                l2 = l2.next
                new_node = new_node.next
            if carry:
                new_node.next =  ListNode(carry)
            return head.next

    c++实现:

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode() : val(0), next(nullptr) {}
     *     ListNode(int x) : val(x), next(nullptr) {}
     *     ListNode(int x, ListNode *next) : val(x), next(next) {}
     * };
     */
    class Solution {
    public:
        ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
            ListNode* head = new ListNode(0);
            ListNode* new_head = head;
            int carry = 0;
            while(l1 && l2){
                new_head->next = new ListNode(l1->val + l2->val + carry);
                carry = new_head->next->val/10;
                new_head->next->val = new_head->next->val%10;            
                new_head = new_head->next;
                l1 = l1->next;
                l2 = l2->next;
            }
    
            while(l1){
                new_head->next = new ListNode(l1->val + carry);
                carry = new_head->next->val/10;
                new_head->next->val = new_head->next->val%10;  
                new_head = new_head->next;
                l1 = l1->next;
            }
            while(l2){
                new_head->next = new ListNode(l2->val + carry);
                carry = new_head->next->val/10;
                new_head->next->val = new_head->next->val%10;  
                new_head = new_head->next;
                l2 = l2->next;
            }
            if(carry){
                new_head->next = new ListNode(carry);
            }
            return head->next;
    
    
    
        }
    };

    ?3.无重复字符的最长子串

    思路:滑动窗口,先往右拓展字典进行加1,发现大于1的在往左压缩 python代码

    class Solution:
        def lengthOfLongestSubstring(self, s):
            n = len(s)
            left = 0
            right = 0
            dict_= {}
            res  =  0
            while right<n:#往右拓展
                dict_[s[right]] = dict_.get(s[right], 0)+1#出现就加1
                while dict_[s[right]]>1:#解决这种两个连续ww的问题"pwwkew" 再次出现往左压缩
                    dict_[s[left]]-=1
                    left+=1
    
                res  = max(res, right-left+1)
                right+=1
            return res
    
    # s = "abcabcbb"
    # s = "dvdf"
    s = "pwwkew"
    sol = Solution()
    sol.lengthOfLongestSubstring(s)

    c++代码:

    #include <string>
    #include <iostream>
    #include <vector>
    #include <list>
    #include <map>
    #include <typeinfo>
    
    using namespace std;
    
    class Solution {
    public:
        int lengthOfLongestSubstring(string s) {
            int left = 0, right = 0, res = 0;
            unordered_map<char, int> dict_;  //散列表实现 查找更高效
            int length = s.size();
            while(right < length){
                dict_[s[right]]++;
                while (dict_[s[right]] > 1){
                    dict_[s[left]]--;
                    left++;
                }
                right++;
                res = max(right - left, res);
            }
        return res; 
        }
    };
    
    int main()
    {   
        string s = "abcabc";
        // Solution sol;
        // int res;
        // res=  sol.lengthOfLongestSubstring(s);
    
        int res;
        Solution *sol = new Solution();
        res =  sol->lengthOfLongestSubstring(s);
        delete sol;
        sol = NULL;    
        cout<<"res:"<<res<<endl;
        return 0;
    }

    4.寻找两个正序数组的中位数

    思路:双指针,走完剩下的在进行合并 时间复杂度o(m+n) 空间复杂度0(m+n)

    
    class Solution:
        def findMedianSortedArrays(self, nums1, nums2):
            res = []
            i, j = 0, 0
            m, n = len(nums1), len(nums2)
            while i < m and j < n:
                if nums1[i] < nums2[j]:
                    res.append(nums1[i])
                    i += 1
                else:
                    res.append(nums2[j])
                    j += 1
            print('==res:', res)
            print('==i:', i)
            print('==j:', j)
            if i < m:
                res.extend(nums1[i:])
            if j < n:
                res.extend(nums2[j:])
            print('==res:', res)
            if (m+n)%2==0:#偶数
                return (res[(m+n)//2]+res[(m+n)//2-1])/2
            else:#奇数
                return res[(m+n)//2]
    
    
    # nums1 = [1, 1, 3]
    # nums2 = [2]
    nums1 = [1,2]
    nums2 = [3,4]
    sol = Solution()
    res = sol.findMedianSortedArrays(nums1, nums2)
    print(res)

    c++实现:

    class Solution {
    public:
        double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
            int m = nums1.size();
            int n = nums2.size();
            int i=0, j=0;
            vector<double> res;
            while(i<m && j<n){
                if(nums1[i]<nums2[j]){
                    res.push_back(nums1[i]);
                    i++;
                }
                else{
                    res.push_back(nums2[j]);
                    j++;
                }
            }
            while(i<m){
                res.push_back(nums1[i]);
                i++;
            }
            while(j<n){
                res.push_back(nums2[j]);
                j++;
            }
            // for(int i=0;i<res.size(); i++){
            //     cout<<"res:"<<res[i]<<endl;
            // }
            if((m+n)%2){
                return res[(m+n)/2];
            }
            else{
                return (res[(m+n)/2-1] + res[(m+n)/2])*1.0/2.;
            }
            return 0.;
        }
    };

    优化:双指针识别,不用开辟数组空间, 时间复杂度o((m+n)/2) 空间复杂度0(1)

    class Solution {
    public:
        double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
            //双指针吧
            int  m = nums1.size();
            int  n = nums2.size();
            int i=0, j=0;
            float preNum = 0, current = 0;
            while((i + j) <= (m + n)/2){
                preNum = current;
                if((j >= n) || (i < m && nums1[i] < nums2[j])){
                    current = nums1[i];
                    i++;
                }
                else{
                    current = nums2[j];
                    j++;
                }
            }
            if((m + n)%2 == 0){
                return (current + preNum) / 2;
            }
            else{
                return current;
            }
        }
    };

    5.最长回文子串

    思路:中心枚举

    class Solution:
        def helper(self,left,right,s):
            while left>=0 and right<len(s) and s[left]==s[right]:
                left-=1
                right+=1
            if len(s[left+1:right])>len(self.res):
                self.res = s[left+1:right]
        def longestPalindrome(self, s: str) -> str:
            self.res = ''
            for i in range(len(s)):
                self.helper(i,i,s)
                self.helper(i,i+1,s)
            return self.res
    

    c++实现:

    class Solution {
    public:
        string res;
        void help(int left, int right, string& s){
            while(left >= 0 && right < s.size() && s[left] == s[right]){
                left--;
                right++;
            }
            left++;
            right--;
            if(right - left + 1 > res.size()){
                res = s.substr(left, right - left + 1);
                }
        }
        string longestPalindrome(string s) {
            if(s.size() <= 1){
                return s;
            }
            for(int i=1; i<s.size(); i++){
                help(i-1, i+1, s);
                help(i-1, i, s);
                }
            return res;
        }
    };
    
    

    ?6,盛最多水的容器

    ?

    求Max{(j-i) * Min( h(i), h(j) )},?

    思路:双指针

    时间复杂度为 O(n),空间复杂度为 O(1) 。?

    #解法2
    class Solution:
        def maxarea(self,height):
            left=0
            right=len(height)-1
            max_area=0
    
            while left<right:
                max_area = max(max_area,(right - left) * min(height[left], height[right]))
                if height[left]<height[right]:
                    left+=1
                else:
                    right-=1
                # index_i = left
                # index_j=right
    
            return max_area
    
    s=Solution()
    height=[2,8,1,5,9,3,4]
    max_area=s.maxarea(height)
    print(max_area)

    c++实现:

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

    ?7.三数之和

    思路1: 固定两数,寻找第三个数,两层循环,最复杂解法,列表比较大时,时间会很长

    class Solution:
        def threeSum(self, nums):
            """
            :type nums: List[int]
            :rtype: List[List[int]]
            """
            result=[]
            nums.sort()
            length=len(nums)
            for i in range(length-1):
                for j in range(i+1,length):
                    if -(nums[i]+nums[j]) in nums[j+1:]:
                        tmp=[nums[i],nums[j],-(nums[i]+nums[j])]
                        if tmp not in result:
                            result.append(tmp)
            return  result

    思路2: 双指针,固定一个数,让其余两个数从第一个数+1和尾 向中间靠近,只需要循环一遍

    # 双指针:排好序以后,双指针去寻找两数之和等于第一个
    class Solution:
        def threeSum(self, nums):
            nums = sorted(nums)
            res = []
            n = len(nums)
            print('==nums:', nums)
            for i in range(n):
                if i>0 and nums[i]==nums[i-1]:#去除相同的第一个数[-1, 0, 1, 2, -1, -4]
                    continue
                start = i + 1
                end = n - 1
                # print('==start:', start)
                # print('==end:', end)
                while start < end:
                    if nums[i] + nums[start] + nums[end] == 0:
                        res.append([nums[i], nums[start], nums[end]])
                        start += 1
                        end -= 1
                        while start<end and nums[start]==nums[start-1]:# 首部出现连续两个数[-2, 0, 0, 2, 2]
                            start+=1
                        while start<end and nums[end]==nums[end+1]:# 尾部出现连续两个数[-2, 0, 0, 2, 2]
                            end-=1
                    elif (nums[i] + nums[start] + nums[end]) > 0:
                        end -= 1
                    else:
                        start += 1
            print('==res:', res)
            return res
    
    # nums = [-1, 0, 1, 2, -1, -4]
    nums = [-2, 0, 0, 2, 2]
    sol = Solution()
    sol.threeSum(nums)

    c++实现:

    class Solution {
    public:
        vector<vector<int>> threeSum(vector<int>& nums) {
            vector<vector<int>> res;
            sort(nums.begin(), nums.end());
            int n = nums.size();
            for(int i=0; i<n; i++){
                if(i>0 && nums[i]==nums[i-1]){
                    continue;
                }
                int start = i + 1;
                int end = n - 1;
                 while(start < end){
                     if(nums[i] + nums[start] + nums[end] == 0){
                        res.push_back({nums[i], nums[start], nums[end]});
                        start++;
                        end--;
                        while(start < end && nums[start]==nums[start-1]){
                            start++;
                        }
                        while(start < end  && nums[end]==nums[end+1]){
                            end--;
                        }
                     }
                     else if((nums[i] + nums[start] + nums[end]) > 0){
                         end--;
                     }
                     else{
                         start++;
                     }
                 }
            }
            return res;
        }
    };

    思路3.利用两数之和

    class Solution:
        def twoSum(self, nums, target):
            res_dict = {}
            for i in range(len(nums)):
                value = -target - nums[i]
                if value in res_dict:
                    self.res.add((target, nums[i], value))
                res_dict[nums[i]] = i
        def threeSum(self, nums: List[int]) -> List[List[int]]:
            self.res = set()
            nums = sorted(nums)
            for i in range(len(nums)):
                if i>0 and nums[i] == nums[i-1]:
                    continue
                self.twoSum(nums[i+1:], nums[i])
            return list(self.res)
        

    8.电话号码的字母组合

    思路:组合问题 用回溯

    
    class Solution:
        def backtrace(self, digits, track):
            if len(digits) == 0:#满足终止条件
                self.res.append(track)
                return
            for letter in self.phone[digits[0]]:# for循环去遍历选择条件
                store = track#保存中间结果用于回溯
                track += letter
                self.backtrace(digits[1:], track)
                track = store#恢复中间结果回溯
    
        def letterCombinations(self, digits):
            self.res = []
            if len(digits) == 0:
                return self.res
    
            self.phone = {'2': ['a', 'b', 'c'],
                          '3': ['d', 'e', 'f'],
                          '4': ['g', 'h', 'i'],
                          '5': ['j', 'k', 'l'],
                          '6': ['m', 'n', 'o'],
                          '7': ['p', 'q', 'r', 's'],
                          '8': ['t', 'u', 'v'],
                          '9': ['w', 'x', 'y', 'z']}
            self.backtrace(digits, track='')
            print('==self.res:', self.res)
            return self.res
    
    
    digits = "23"
    sol = Solution()
    sol.letterCombinations(digits)
    

    9.删除链表的倒数第N个节点

    思路:找到链表长度,通过在头结点补充一个节点找到要删除的节点的上一个节点,然后在进行删除

    方法1:循环

    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, val=0, next=None):
    #         self.val = val
    #         self.next = next
    class Solution:
        def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
            length = 0 
            node = head
            #获取链表长度
            while node:
                length+=1
                node= node.next
            # print(length)
    
            curr_length = 0
            new_head = ListNode(0)
            new_head.next = head
            node2=new_head
            stop_length = length - n
            #循环走到要删除节点的前一个节点
            while stop_length:
                stop_length-=1
                node2 = node2.next
            #跳过要删除的节点即可
            node2.next = node2.next.next
            return new_head.next
    

    方法2:递归

    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, val=0, next=None):
    #         self.val = val
    #         self.next = next
    class Solution:
        def __init__(self):
            self.count = 0
        def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
            if not head:            
                return head  
            
            head.next = self.removeNthFromEnd(head.next, n) # 递归调用
            self.count += 1 # 回溯时进行节点计数
            return head.next if self.count == n else head 
    

    方法3:双指针 推荐使用

    fist 指针与second指针相隔n,这样first跑到尾部,second的下一个节点就是倒数第n个

    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, val=0, next=None):
    #         self.val = val
    #         self.next = next
    class Solution:
        # def __init__(self):
        #     self.count = 0
        def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
            new_head =  ListNode(0)
            new_head.next = head
            first  = head
            second = new_head
            for i in range(n):
                first = first.next
            while first:
                first = first.next
                second = second.next
            second.next = second.next.next
            return new_head.next

    c++实现:?

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode() : val(0), next(nullptr) {}
     *     ListNode(int x) : val(x), next(nullptr) {}
     *     ListNode(int x, ListNode *next) : val(x), next(next) {}
     * };
     */
    class Solution {
    public:
        ListNode* removeNthFromEnd(ListNode* head, int n) {
            ListNode* new_head = new ListNode(0);
            new_head ->next = head;
            ListNode* first = head;
            ListNode* second = new_head;
            for(int i=0;i<n;i++){
                first = first->next;
            }
            while(first){
                first = first->next;
                second = second->next;
            }
            second->next = second->next->next;
            return new_head->next;
        }
    };

    10.有效的括号

    思路: 栈

    class Solution:
        def isValid(self, s: str) -> bool:
            stack= []
            dict_ = {
                ')':'(',
                '}':'{',
                ']':'[',
            }
            for i in range(len(s)):
                if s[i] in dict_.keys():
                    if len(stack) == 0 or stack[-1] != dict_[s[i]]:
                        return False
                    else:
                        stack.pop()
                else:
                    stack.append(s[i])
            return len(stack) == 0

    11.合并两个排序的链表

    思路:引入一个指针头 python实现

    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.next = None
    
    class Solution:
        def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
    
            head = ListNode(0)
            node = head
    
            while l1 and l2:
                if l1.val < l2.val:
                    node.next = l1
                    l1 = l1.next
                else:
                    node.next = l2
                    l2 = l2.next
                node = node.next
            if l1 is not None:
                node.next= l1
            if l2 is not None:
                node.next= l2
            return head.next

    c++实现:

    /**
     * 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* new_head = new ListNode(0);
            ListNode* node = new_head;
    
            while(l1!=NULL && l2 !=NULL){
                if(l1->val<l2->val){
                    node->next = l1;
                    l1 = l1->next;
                }
                else{
                    node->next  = l2;
                    l2 = l2->next;                
                }
                node = node->next;
            }
    
            if (l1!=NULL){
                node->next = l1;
            }
            if(l2!=NULL){
                node->next = l2;
            }
            return new_head->next;
        }
    };

    12.括号生成

    思路:回溯剪枝

    1.左右括号插入数量不能超过n

    2.左括号数量大于右括号,就可以插入右括号

    
    # 回溯法:插入数量不超过n
    # 可以插入 ) 的前提是 ( 的数量大于 )
    class Solution(object):
    
        def generateParenthesis(self, n):
            """
            :type n: int
            :rtype: List[str]
            """
            self.res = []
            self.dfs(n, n, '')
            return self.res
    
        def dfs(self, left, right, track):
            if left == 0 and right == 0:  # 递归终止条件 左括号与右括号都用完
                self.res.append(track)
                return
    
            if left > 0:  # 左括号个数
                store = track  #
                track += '('
                self.dfs(left - 1, right, track)
                track = store
            if left < right:  # 左括号个数大于右括号 此时可以添加右括号
                # store = track
                track += ')'
                self.dfs(left, right - 1, track)
                # track = store
    
    
    n = 2
    sol = Solution()
    res = sol.generateParenthesis(n)
    print(res)

    13.合并K个升序链表

    思路1:上一题合并两个变成for循环顺序合并

    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, val=0, next=None):
    #         self.val = val
    #         self.next = next
    class Solution:
        def mergeTwo(self, l1, l2):
            if l1 is None:
                return l2
            if l2 is None:
                return l1
            head = ListNode(0)
            node = head
            while l1 and l2:
                if l1.val <l2.val:
                    node.next = l1
                    l1 = l1.next
                else:
                    node.next = l2
                    l2 = l2.next
                node = node.next
            if l1:
                node.next = l1
            if l2:
                node.next = l2
            return head.next
    
        def mergeKLists(self, lists: List[ListNode]) -> ListNode:
            ans  = None
            for i in range(len(lists)):
                ans = self.mergeTwo(ans,lists[i])
            return ans

    c++:

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode() : val(0), next(nullptr) {}
     *     ListNode(int x) : val(x), next(nullptr) {}
     *     ListNode(int x, ListNode *next) : val(x), next(next) {}
     * };
     */
    class Solution {
    public:
        ListNode* mergtwo(ListNode* l1, ListNode* l2){
            if(l1==nullptr){
                return l2;
            }
            if(l2==nullptr){
                return l1;
            }
            ListNode* new_head= new ListNode(0);
            ListNode* node = new_head;
            while(l1 && l2){
                if(l1->val<l2->val){
                    node->next = l1;
                    l1= l1->next;
                }
                else{
                    node->next = l2;
                    l2= l2->next;
                }
                node = node->next;
            }
            if(l1){
                node->next = l1;
            }
            if(l2){
                node->next = l2;
            }
            return new_head->next;
        }
        ListNode* mergeKLists(vector<ListNode*>& lists) {
            ListNode* res = nullptr;
            for (int i=0;i<lists.size();i++){
                res = mergtwo(res,lists[i]);
            }
            return res;
        }
    };
    
    下一篇:没有了