leetcode Top 100 Liked Questions Python详解

文章目录

题目难度复杂度解法备注话题
1.两数之和Easy O ( n 2 ) ; O ( n ) O(n^2);O(n) O(n2)O(n)暴力法;保存哈希表Done数组、哈希表
3. Longest Substring Without Repeating CharactersMedium O ( n ) O(n) O(n)遍历哈希表保存每个字符的初始位置ToDo
4. Median of Two Sorted ArraysMedium O ( n l o g n ) , O ( l o g ( m i n ( m , n ) ) O(nlogn),O(log(min(m,n)) O(nlogn),O(log(min(m,n))传统解法+中位数的数学推导
5.Longest Palindromic SubstringMedium O ( n 3 ) O(n^3) O(n3)暴力解法,遍历然后判断每个子字符串是否为回文Done
11. Container With Most WaterMedium O ( n 2 ) , O ( n ) O(n^2), O(n) O(n2),O(n)暴力解法获取每个区间,求最大;双指针,从外向里移动Done
15. 3SumMedium O ( n l o g n ) , O ( n 2 ) O(nlogn),O(n^2) O(nlogn),O(n2)双指针
17. Letter Combinations of a Phone NumberMedium递归
19. Remove Nth Node From End of ListMedium O ( n ) O(n) O(n)设置哑结点
21. Merge Two Sorted ListsEasy O ( m + n ) O(m+n) O(m+n)设置哑节点,然后类似list,依次选择较小的一个Done链表
22.Generate ParenthesesMedium O ( 2 2 n n ) ; O(2^{2n}n); O(22nn);暴力做法;回溯法,前面的序列有效时才增加"(“或”)"
23.Merge k Sorted ListsHard O ( n l o g n ) O(nlogn) O(nlogn)暴力法;分置变成双链表问题ToDo
31.Next PermutationMedium O ( n ! ) O(n!) O(n!)暴力法;遍历,替换ToDo
32.Longest Valid ParenthesesHard O ( n 3 ) ; O ( n ) O(n^3);O(n) O(n3)O(n)暴力法;数学规律ToDo
33.Search bia Rotated Sorted ArrayMedium O ( n ) O(n) O(n)遍历;Done
34.Find First and Last Position of Element in Sorted ArrayMedium O ( n ) ; O ( l o g n ) O(n);O(logn) O(n);O(logn)遍历;二分查找Done
39.Combination SumMedium递归ToDo
41.缺失的第一个正数Hard O ( n ) O(n) O(n)主要是边界情况Done数组
42. Trapping Rain WaterHard O ( n 2 ) ; O ( n ) O(n^2);O(n) O(n2)O(n)暴力;双指针ToDO
46.PermutationsMedium递归ToDo
48.Medium O ( n 2 ) O(n^2) O(n2)翻转然后转置Done
53. Maximum SubarrayEasy O ( n 2 ) ; O ( n ) O(n^2);O(n) O(n2)O(n)遍历所有子序列;Done
55. Jump GameMedium O ( n ) O(n) O(n)贪心法,从右到左ToDo
56. Merge IntervalsMedium O ( n l o g n ) O(nlogn) O(nlogn)排序,然后进行区间合并Done
62. Unique PathsMedium O ( m a x ( m , n ) ! ) ; O ( n 2 ) O(max(m,n)!);O(n^2) O(max(m,n)!)O(n2)一共m+n-2步,选择m-1种向下的走法;DPToDo
64. Minimum Path SumMedium O ( ) O() O()动态规划ToDo
70.Climbing StairsEasy O ( n ) O(n) O(n)斐波那契数列ToDo
72.Edit DistanceHardMedium O ( n ) O(n) O(n)动态规划ToDo
75. Sort ColorsMedium O ( n ) O(n) O(n)直接排序,或者对0,2进行操作Done
76. Minimum Window SubstringHard O ( S + T ) O(S+T) O(S+T)双指针+滑动窗口ToDo
84. Largest Rectangle in HistogramHard O ( n ) O(n) O(n)ToDo
86.分割链表Medium O ( n ) O(n) O(n)设置两个临时结点Done链表
94. Binary Tree Inorder TraversalMedium递归和非递归方法ToDo
102.二叉树的层次遍历Medium O ( N ) O(N) O(N)队列保存每个结点ToDo二叉树
114.二叉树展开成链表Medium O ( N ) O(N) O(N)前序遍历然后保存在list中;inplaceToDo二叉树
121. Best Time to Buy and Sell StockEasy O ( n 2 ) ; O ( n ) O(n^2);O(n) O(n2);O(n)暴力; 一次遍历,依次当前值前面的最小值Done
122. Best Time to Buy and Sell Stock IIEasy O ( n n ) ; O ( n ) O(n^n);O(n) O(nn)O(n)暴力法和一次遍历ToDo
128. Longest Consecutive SequenceHard O ( n l o g n ) ; O ( n ) O(nlogn);O(n) O(nlogn)O(n)排序后遍历ToDo
136.只出现一次的数字Easy O ( n ) O(n) O(n)哈希表;位操作;数学方法Done数组
137.只出现一次的数字IIMedium O ( n ) O(n) O(n)哈希表;位操作;数学方法Done数组
138. 复制带随机指针的链表Medium O O OToDo链表
141. Linked List CycleEasy O ( n ) O(n) O(n)哈希表或者快慢指针Done链表
142. Linked List Cycle IIMedium O ( n 2 ) , O ( n ) O(n^2),O(n) O(n2),O(n)哈希表或者快慢指针Done链表
152.Maximum Product SubarrayMedium O ( n 2 ) ; O ( n ) O(n^2);O(n) O(n2)O(n)暴力法;前后遍历,得到乘积Done
155. Min StackEasy建立辅助栈Done
160.相交链表Easy保存前一个为set遍历另外一个,数学方法遍历Done链表
169.求众数Easy O ( n ) O(n) O(n)哈希表保存出现次数Done
198. 打家劫舍Easy O n ( ) On() On()动态规划ToDo
200. 岛屿的个数MediumDFSToDo
206.反转链表Easy O ( m ) O(m) O(m)交换既可Done链表
208.实现前缀树Medium直接实现Done
215. 数组中的第K个最大元素Medium O ( n l o g n ) O(nlogn) O(nlogn)排序,然后求解Done
221.最大正方形MediumToDo
226.翻转二叉树Easy O ( l o g n ) O(logn) O(logn)递归,翻转Done
234.回文链表Easy O ( n ) O(n) O(n)保存在list中然后判断是否是回文Done
236.二叉树的最近公共祖先Medium O ( n ) O(n) O(n)ToDo
238.除自身以外的数组的乘积Medium O ( n ) O(n) O(n)除法;前后累积乘积ToDo
239.滑动窗口最大值Hard O ( k n ) ; O ( n ) O(kn);O(n) O(kn);O(n)滑动遍历求最值;Done
240.搜索二维矩阵Medium O ( n 2 ) ; O ( n ) O(n^2);O(n) O(n2)O(n)观察规律Done
264丑数Easy O ( n ) O(n) O(n)判断是否是2,3,5的倍数不断除Done数学
265.丑数IIMedium依次生成即可,保存较小的值Done数学
279.完全平方数MediumTodo
283.移动零Medium O ( n ) O(n) O(n)遍历,去除,保存Done
287.寻找重复数Medium O ( n ) O(n) O(n)哈希表保存次数Done
297. 二叉树的序列化与反序列化HardDone
300.最长上升子序列MediumToDo
309.最佳买卖股票时机含冷冻期MediumToDo
312. 戳气球HardToDo
322.零钱兑换Medium动态规划ToDo
409. Longest PalindromeEasy O ( n 2 ) O(n^2) O(n2)统计次数,判断奇偶Done
461.汉明距离Easy O ( n ) O(n) O(n)异或然后判断二进制中1的个数Done
494. 目标和MediumDFSToDo
581. 最短无序连续子数组Easy O ( n l o g n ) O(nlogn) O(nlogn)排序然后遍历比较Done
617.合并二叉树Medium O ( m ) O(m) O(m)递归;循环Done
647. 回文子串Medium O ( n 3 ) , O ( n 2 ) O(n^3), O(n^2) O(n3),O(n2)暴力解法;遍历字符串以每个字符为中心Done
771. Jewels and StonesEasy O ( m n ) O(mn) O(mn)巨简单

1.两数之和

暴力法
哈希表 O ( n ) O(n) O(n) 遍历数组将数组保存在哈希表中,key:num,value:index,然后再遍历数组,判断target-num是否在哈希表里面,保证该元素不能是他自身。

# 此方法需要遍历两边数组
class Solution(object):
# 56ms 93.92%
    def twoSum(self, nums, target):
        nums_dict = dict()
        for index in range(len(nums)):
            nums_dict[nums[index]] = index
            
        for index in range(len(nums)):
            temp = target-nums[index]
            if temp in nums_dict and nums_dict[temp] != index:
                return [index,nums_dict[temp]]

# 仅需遍历一遍数组的
class Solution(object):
    def twoSum(self, nums, target):
        nums_dict = dict()
        for index in range(len(nums)):
            temp = target-nums[index]
            if temp in nums_dict:
                return [index,nums_dict[temp]]
            nums_dict[nums[index]] = index

3. Longest Substring Without Repeating Characters

暴力解法,遍历所有子字符串,然后判断所有字符串是否重复,求不重复的最大值

class Solution(object):
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """
        if s == '':
            return 0
        if len(s) == 1:
            return 1
        len_list = []
        for i in range(len(s)-1):
            for j in range(i+1, len(s)+1):
                temp = s[i:j]
                # print(temp)
                if len(set(temp)) == len(temp):
                    len_list.append(len(temp))
        return max(len_list)

用一个Hash表保存每一个char出现的位置,如果出现重复,那么将这个char重复出现的位置和第一次出现的位置相减。

class Solution(object):
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """
        char_dict = {}
        start = 0
        maxlen = 0
        for index, char in enumerate(s):
            if char in char_dict and char_dict[char] >= start:
                maxlen = max(maxlen, index-start)
                start = char_dict[char] + 1
            char_dict[char] = index
        return max(maxlen, len(s)-start)

4. Median of Two Sorted Arrays

暴力解法,4ms

class Solution:
    def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
        nums1.extend(nums2)

        length = len(nums1)
        nums1 = sorted(nums1)

        if len(nums1)%2 == 0:
            return (nums1[int(length/2)-1] + nums1[int(length/2)])/2
        else:
            return nums1[int((length-1)/2)]

5.Longest Palindromic Substring

暴力解法,遍历然后判断是否是回文。

class Solution:
    def longestPalindrome(self, string):
        """
        :type s: str
        :rtype: str
        """
        length = len(string)
        max_len = 0
        result = ''
        if len(string) == 1:
            return string
        for i in range(length):
            for j in range(i+1,length+1):
                temp = string[i:j]
    #             print(temp,i,j)
                if temp == temp[::-1] and len(temp) > max_len:
                    max_len = len(temp)
                    result = temp
        return result

遍历字符串,以单个字符为中心向外延展,取字符串长度最长的。考虑”aba“和”abba“这两种情况。

class Solution(object):
    def longestPalindrome(self, s):
        res = ""
        for i in range(len(s)):
            # odd case, like "aba"
            tmp = self.helper(s, i, i)
            if len(tmp) > len(res):
                res = tmp
            # even case, like "abba"
            tmp = self.helper(s, i, i+1)
            if len(tmp) > len(res):
                res = tmp
        return res

    # get the longest palindrome, l, r are the middle indexes   
    # from inner to outer
    def helper(self, s, l, r):
        while l >= 0 and r < len(s) and s[l] == s[r]:
            l -= 1; r += 1
        return s[l+1:r]   

11.Container With Most Water

class Solution(object):
    def maxArea(self, height):
        """
        :type height: List[int]
        :rtype: int
        """
        maxarea = 0
        for i in range(len(height)-1):
            for j in range(i+1, len(height)):
                area =  (j-i)*min(height[i],height[j])
                if area > maxarea:
                    maxarea = area
        return maxarea

双指针,从两边向里移动,移动start和end中小的那一个

class Solution:
    def maxArea(self, height):
        """
        :type height: List[int]
        :rtype: int
        """
        max_area,left,right = 0,0,len(height)-1
        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
        return max_area

15. 3Sum:

暴力解法, O ( n 3 ) O(n^3) O(n3)

class Solution(object):
    def threeSum(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        if len(nums) < 3:
            return
        result = []
        nums = sorted(nums)
        
        result_str = []
        for i in range(len(nums) - 2):
            for j in range(i+1, len(nums) - 1):
                for k in range(j+1, len(nums)):
                    result1 = ''.join([str(nums[i]),str(nums[j]), str(nums[k])])
                    if nums[i] + nums[j] + nums[k] == 0 and result1 not in result_str:
                        
                        result.append([nums[i],nums[j], nums[k]])
                        result_str.append(result1)
        return result

双指针,做成Two-Sum问题:

class Solution(object):
    def threeSum(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        nums = sorted(nums)
        result = []
        for i in range(len(nums)-2):
            if i > 0 and nums[i] == nums[i-1]:
                continue
            left = i+1

            right = len(nums) - 1
            while left < right:
                sum1 = nums[i] + nums[left] + nums[right]
                if sum1 < 0:
                    left += 1
                elif sum1 == 0:
                    result.append([nums[i],nums[left], nums[right]])
                    left += 1
                    right -= 1
                    while left < right and nums[left] == nums[left-1]:
                        left += 1
                    while right > left and nums[right] == nums[right+1]:
                        right -= 1
                else:
                    right -= 1
        return result

17. Letter Combinations of a Phone Number

采用递归来写,

class Solution(object):
    def letterCombinations(self, digits):
        """
        :type digits: str
        :rtype: List[str]
        """
        kvmaps = {
        '2': 'abc',
        '3': 'def',
        '4': 'ghi',
        '5': 'jkl',
        '6': 'mno',
        '7': 'pqrs',
        '8': 'tuv',
        '9': 'wxyz'
        }
        if len(digits) == 0:
            return []
        if len(digits) == 1:
            return list(kvmaps[digits[0]])

        return [str1 + char1 for str1 in self.letterCombinations(digits[:-1]) for char1 in kvmaps[digits[-1]]]

19. Remove Nth Node From End of List:

首先确定链表的长度L,删除倒数第N个,即删除正数第L-N+1个;

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution(object):
    def removeNthFromEnd(self, head, n):
        """
        :type head: ListNode
        :type n: int
        :rtype: ListNode
        """
        dummy = ListNode(0)
        length = 0
        dummy.next = head
        
        first = head
        while first != None:
            length += 1
            first = first.next
        
        length -= n
        first = dummy
        while length > 0:
            length -= 1
            first = first.next
        
        first.next = first.next.next
        return dummy.next

两个指针,第一个指针走n个后,另一个指针再开始,第一个指针到最后的时候,第二个指针到达倒数第n个。

class Solution(object):
    def removeNthFromEnd(self, head, n):
        dummy = ListNode(0)
        dummy.next = head
        
        first = dummy
        second = dummy
        
        for i in range(n+1):
            first = first.next
            
        while first != None:
            first = first.next
            second = second.next
        second.next = second.next.next
        return dummy.next

21. Merge Two Sorted Lists

递归: 一次保存两个链表中较小 一个。

class Solution(object):
    def mergeTwoLists(self, pHead1, pHead2):
        # write code here
        if pHead1 == None:
            return pHead2
        if pHead2 == None:
            return pHead1
        
        pMergeHead = None
        if pHead1.val < pHead2.val:
            pMergeHead = pHead1
            pMergeHead.next = self.mergeTwoLists(pHead1.next, pHead2)
        else:
            pMergeHead = pHead2
            pMergeHead.next = self.mergeTwoLists(pHead1, pHead2.next)
        return pMergeHead

循环: 判断l1和l2是否为空,依次取较小的一个,然后合并l1和l2,有一个可能提前遍历完,直接拼接另一个即可。

class Solution(object):
    def mergeTwoLists(self, l1, l2):
        dummy = cur = ListNode(0)
        while l1 and l2:
            if l1.val < l2.val:
                cur.next = l1
                l1 = l1.next
            else:
                cur.next = l2
                l2 = l2.next
            cur = cur.next
        cur.next = l1 or l2
        return dummy.next

22.Generate Parentheses

暴力做法,生成所有的表示“()”字符构成的序列,然后判断该字符是否是有效的。通过递归来生成所有的序列。平衡字符来判断该序列是否是有效的。

class Solution(object):
# 148ms
# 13.5MB
    def generateParenthesis(self, n):
        def generate(A = []):
            if len(A) == 2*n:
                if valid(A):
                    ans.append("".join(A))
            else:
                A.append('(')
                generate(A)
                A.pop()
                A.append(')')
                generate(A)
                A.pop()

        def valid(A):
            bal = 0
            for c in A:
                if c == '(': bal += 1
                else: bal -= 1
                if bal < 0: return False
            return bal == 0

        ans = []
        generate()
        return ans

回溯法:当当前序列有效时才增加新的括号“()”。判断的标准是左括号的数目,保证左括号数量小于N,如果右括号数量小于左括号数目那么增加右括号数目。

class Solution(object):
# 56ms
# 13.4MB
    def generateParenthesis(self, N):
        ans = []
        def backtrack(S = '', left = 0, right = 0):
            if len(S) == 2 * N:
                ans.append(S)
                return
            if left < N:
                backtrack(S+'(', left+1, right)
            if right < left:
                backtrack(S+')', left, right+1)

        backtrack()
        return ans

23.Merge k Sorted List:

暴力法 O ( n l o g n ) O(nlogn) O(nlogn):保存所有链表的数值,然后对其进行排序,将排序后的list转换成链表

class Solution(object):
# 88ms
# 20MB
    def mergeKLists(self, lists):
        """
        :type lists: List[ListNode]
        :rtype: ListNode
        """
        all_list = []
        head = point = ListNode(0)
        for List in lists:
            while List:
                all_list.append(List.val)
                List = List.next
        all_list = sorted(all_list)
        for num in all_list:
            point.next = ListNode(num)
            point = point.next
        return head.next

分置算法:
将这k个排序链表一分为二,不断持续下去,将其变成双链表合并问题。

class Solution:
    def mergeKLists(self, lists: List[ListNode]) -> ListNode:
        if not lists:
            return []
        
        if len(lists) == 1:
            return lists[0]
        
        mid = len(lists) // 2
        
        ll = self.mergeKLists(lists[:mid])
        rl = self.mergeKLists(lists[mid:])
        
        return self.merge2List(ll,rl)        
        
        
    def merge2List(self, l, r):
        root = ListNode(0)
        cur = root
        while l and r:
            if l.val < r.val:
                cur.next = l
                l = l.next
                cur = cur.next
                
            else:
                cur.next = r
                r = r.next
                cur = cur.next
                
        if l:
            cur.next = l
        else:
            cur.next = r
                
        return root.next

31.Next Permutation

暴力法:
生成所有可能的排列情况,然后找到最接近的那个排列。
从右到左遍历list,如果第i个数比第i+1数小,那么这个数应该被替换。这个数的右边是一个递减序列。将这个数替换成右边序列比第i个数大,但最接近的那个。然后将右边的数做逆序排列。

class Solution:
    def nextPermutation(self, nums):
        """
        :type nums: List[int]
        :rtype: void Do not return anything, modify nums in-place instead.
        """
        i = len(nums) - 2
        while i >= 0 and nums[i] >= nums[i+1]:
            i -= 1

        if i>=0:
            j = len(nums) - 1
            while j >=0 and nums[i] >= nums[j]:
                j -= 1

            temp = nums[i]
            nums[i] = nums[j]
            nums[j] = temp
        nums[i+1:] = nums[i+1:][::-1]

32. Longest Valid Parentheses

暴力法,生成所有的子序列,然后判断是否是有效序列,保存有效序列的长度,求最值:

class Solution:
    def longestValidParentheses(self, s):
        """
        :type s: str
        :rtype: int
        """
        def Isvalid(s):
            num = 0
            for char in s:
                if char == '(':
                    num += 1
                else:
                    num -= 1
                if num < 0:
                    return False
            return num == 0
        result = []
        for i in range(len(s)-1):
            for j in range(i+1, len(s)+1):
                temp_s = s[i:j]
                if Isvalid(temp_s):
                    result.append(len(temp_s))
        if result == []:
            return 0
        return max(result)

利用数学规律,首先从左到右遍历,遇到“(”,left+1,遇到")",right+1。如果left和right再次相等,则为有效序列,判断其是否为最长序列,同时令left和right均为0,如果right>left也置零。从右到左做同样的遍历。

# 52 ms
# 13.2 Mb
class Solution(object):
    def longestValidParentheses(self, s):
        """
        :type s: str
        :rtype: int
        """
        left,right,maxlength = 0,0,0
        for i in range(len(s)):
            if s[i] == '(':
                left += 1
            else:
                right += 1
            if left == right:
                maxlength = max(maxlength, 2*right)
            elif right > left:
                left = 0
                right = 0
        left = right = 0
        for i in range(len(s)-1,-1,-1):
            if s[i] == '(':
                left += 1
            else:
                right += 1
            if left == right:
                maxlength = max(maxlength, 2*left)
            elif left >= right:
                left = right = 0
        return maxlength   

33.Search in Rotated Sorted Array:

遍历list,然后得到index:

class Solution(object):
    def search(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        if target not in nums:
            return -1
        return nums.index(target)

二分法:
和旋转数组寻找最小值不一样,只要判断middle和left,right的大小即可。这要分成多种情况讨论。旋转点在middle右侧和旋转点在middle左侧,然后又分为两种情况。

class Solution:
    # @param {integer[]} numss
    # @param {integer} target
    # @return {integer}
    def search(self, nums, target):
        if not nums:
            return -1

        low, high = 0, len(nums) - 1

        while low <= high:
            mid = (low + high) >> 1
            if target == nums[mid]:
                return mid

            if nums[low] <= nums[mid]:
                if nums[low] <= target <= nums[mid]:
                    high = mid - 1
                else:
                    low = mid + 1
            else:
                if nums[mid] <= target <= nums[high]:
                    low = mid + 1
                else:
                    high = mid - 1

        return -1

def search(self, nums, target):
    lo, hi = 0, len(nums) - 1
    while lo < hi:
        mid = (lo + hi) / 2
        if (nums[0] > target) ^ (nums[0] > nums[mid]) ^ (target > nums[mid]):
            lo = mid + 1
        else:
            hi = mid
    return lo if target in nums[lo:lo+1] else -1

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

暴力做法,找到所有满足条件的数字,然后求index的最大最小值

class Solution(object):
    def searchRange(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        result = [index for index,item in enumerate(nums) if item == target]
        if len(result) == 0:
            result = [-1, -1]
        return [min(result),max(result)]
        

双指针,在整个list范围,建立两个指针,从两头开始遍历:

# 108ms
# 12.9MB
class Solution(object):
    def searchRange(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        if nums == []:
             return [-1,-1]

        left,right = 0,len(nums)-1
        while nums[left] != target or nums[right]!=target:
            if nums[left] != target:
                left += 1
            if nums[right] != target:
                right -= 1
            if left > right:
                return [-1,-1]
        return [left,right]

先找第一个和target相等的点(通过遍历来寻找),然后找最后一个和target相等点:

# 40ms
# 13.8MB
class Solution(object):
    def searchRange(self, nums, target):
        first, last = 0, 0
        i, j = 0, 0
        
        for i in range(len(nums)):
            if nums[i] == target:
                first = i
                break
        else:
            return [-1, -1]
        
        for j in range(i+1, len(nums)):
            if nums[j] != target:
                last = nums[j-1]
                return [i, j-1]
        else:
            return [i, j or i]

分别查找和target相等的第一个点和最后一个点,采用二分查找而不是遍历。

class Solution:
    # returns leftmost (or rightmost) index at which `target` should be inserted in sorted
    # array `nums` via binary search.
    def extreme_insertion_index(self, nums, target, left):
        lo = 0
        hi = len(nums)

        while lo < hi:
            mid = (lo + hi) // 2
            if nums[mid] > target or (left and target == nums[mid]):
                hi = mid
            else:
                lo = mid+1

        return lo


    def searchRange(self, nums, target):
        left_idx = self.extreme_insertion_index(nums, target, True)

        # assert that `left_idx` is within the array bounds and that `target`
        # is actually in `nums`.
        if left_idx == len(nums) or nums[left_idx] != target:
            return [-1, -1]

        return [left_idx, self.extreme_insertion_index(nums, target, False)-1]

39.Combination Sum:

知道采用递归,但是依然不太会,懵逼。

class Solution(object):
    def combinationSum(self, candidates, target):
        """
        :type candidates: List[int]
        :type target: int
        :rtype: List[List[int]]
        """
        candidates = sorted(candidates)
        def combine(start,target):
            answer=[]
            for i in range(start,len(candidates)):
                if target<candidates[i]:
                    break
                if target==candidates[i]:
                    answer.append([target])
                    break
                
                for item in combine(i,target-candidates[i]):
                    item.append(candidates[i])
                    answer.append(item)
            
            return answer
        
        return combine(0,target)

40.组合总和II:

此题不能用循环,因为求和不等于target就不会保存在result里面,后续遍历就获取不到。


41.缺失的第一个正数:

常规法:首先对数组取set,然后从1开始遍历,判断是否在数组里面。注意边界情况:[1,2,3,4],[ ],[-1,-2,-3],[-5]

class Solution(object):
    def firstMissingPositive(self, nums):
        if len(nums) == 0:
            return 1
        nums = set(nums)
        num = 1
        while num <= max(nums):
            if num not in nums:
                return num
            num += 1
        return max(1, max(nums) + 1)

42.Trapping Rain Water

暴力:遍历数组,求每个柱子上面能留存的最多的水,也就是 m i n ( m a x l e f t , m a x r i g h t ) − h e i g h t [ i ] min(maxleft,maxright) - height[i] min(maxleft,maxright)height[i]

class Solution(object):
# 超时
    def trap(self, height):
        """
        :type height: List[int]
        :rtype: int
        """
        ans = 0
        size = len(height)
        
        for i in range(1, size-1):
            max_left,max_right = 0,0
            for j in range(i, -1, -1):
                max_left = max(max_left, height[j])
            for j in range(i, size):
                max_right = max(max_right, height[j])
            
            ans += min(max_left, max_right) - height[i]
        return ans    

双指针,left和right两个指针,设left_max和right_max两个标志位。只要height[left]不大于left_max,那么留存的水便是left_max - height[left]。right如是操作。

class Solution(object):
    def trap(self, height):
        """
        :type height: List[int]
        :rtype: int
        """
        left ,right = 0,len(height)-1
        ans = 0
        left_max, right_max = 0,0
        while left < right:
            if height[left] < height[right]:
                if height[left] >= left_max:
                    left_max = height[left]
                else:
                    ans += left_max - height[left]
                left += 1
            else:
                if height[right] > right_max:
                     right_max = height[right]
                else:
                    ans += right_max - height[right]
                right -= 1
        return ans

46.Permutations

生成数组的全排列。采用递归,遍历数组的每一个字符,然后去除这个字符,递归这个函数。

class Solution(object):
    def permute(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        if nums is None: return []
        if len(nums) == 1: return [nums]
        res = []
        for x in nums:
            ys=nums+[]
            ys.remove(x)
            for y in self.permute(ys):
                res.append([x]+y)
        return res

class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:
        ans = []
        if len(nums) == 0:
            return
        if len(nums) == 1:
            return [nums]
        for index,item in enumerate(nums):
            res = nums[:index]+nums[index+1:] #剩余的数字集合
            for j in self.permute(res): #对剩余的数字进行递归
                ans.append(j+[item])
        return ans

48.Rotate Image

旋转90°相当于首先对矩阵进行reverse然后进行转置。

class Solution:
    def rotate(self, A):
        A.reverse()
        for i in range(len(A)):
            for j in range(i):
                A[i][j], A[j][i] = A[j][i], A[i][j]

非常精彩的代码,一行结束。和上面做法是一样的,但是语法更简洁。

class Solution:
    def rotate(self, A):
        A[:] = map(list, zip(*A[::-1]))

49. Group Anagrams

建立一个Hash表,key是每个string排序后的结果,value是一个list保存key相同的string。

class Solution(object):
    def groupAnagrams(self, strs):
        """
        :type strs: List[str]
        :rtype: List[List[str]]
        """
        result = {}
        for str1 in strs:
            try:
                result[''.join(sorted(str1))] += [str1]
            except:
                result[''.join(sorted(str1))] = [str1]
        return list(result.values())
    
# 与上面的方法一样,但是采用collections类
class Solution(object):
    def groupAnagrams(self, strs):
        ans = collections.defaultdict(list)
        for s in strs:
            ans[tuple(sorted(s))].append(s)
        return ans.values()

53.Maximum Subarray

遍历所有子序列,然后求和比较最大值。

class Solution(object):
    def maxSubArray(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        max_sum = -1e10
        length = len(nums)
        for i in range(length):
            for j in range(i+1, length+1):
                temp = sum(nums[i:j])
                if temp > max_sum:
                    max_sum = temp
        return max_sum

遍历依次数组,比较从前面某一点开始到当前值的求和和当前值的大小。保证到当前值的子序列都是最大的。

class Solution:
    # @param A, a list of integers
    # @return an integer
    # 6:57
    def maxSubArray(self, A):
        if not A:
            return 0

        curSum = maxSum = A[0]
        for num in A[1:]:
            curSum = max(num, curSum + num)
            maxSum = max(maxSum, curSum)

        return maxSum

55. Jump Game:

采用贪心,从最后一个值出发,向前找第一个能到达这个有效值的点。依次判断每个点是否是一个有效点,称为Good Position,否则为Bad Position。判断最后一个有效点是否是零点。

class Solution(object):
    def canJump(self, nums):
        """
        :type nums: List[int]
        :rtype: bool
        """
        length = len(nums)
        lastPos = length - 1
        for i in range(length-1, -1,-1):
            if nums[i] + i >= lastPos:
                lastPos = i
        return lastPos == 0

56. Merge Intervals

首先根据第一个字符对其进行排序,然后判断每个区间的end值是否大于下一个区间的start值,如果大于等于则进行合并。否则直接拼接在result里面即可。

def merge(intervals):
    """
    :type intervals: List[Interval]
    :rtype: List[Interval]
    """
    # 执行用时 : 96 ms
    # 内存消耗 : 16.4 MB
    intervals = sorted(intervals, key=lambda x:x[0])
    result = []

    for list1 in intervals:
        # result为空则
            if not result or result[-1][1] < list1[0]:
                result.append(list1)
            else:
                result[-1][1] = list1[1]
    return result

62. Unique Paths

一个非常秀的做法。从起始点到终点,一共m+n-2步,其中m-1步向下,n-1步向左。所以可以认为是个组合问题,从m+n-2步中选择m-1步作为向下的,也就是 C m + n − 2 m − 1 C^{m-1}_{m+n-2} Cm+n2m1

class Solution(object):
    def uniquePaths(self, m, n):
        """
        :type m: int
        :type n: int
        :rtype: int
        """
        return math.factorial(m+n-2)/math.factorial(m-1)/math.factorial(n-1)

动态规划,软肋,始终无法真正弄懂DP

class Solution(object):
    def uniquePaths(self, m, n):
        table = [[0 for x in range(n)] for x in range(m)]
        for i in range(m):
            table[i][0] = 1
        for i in range(n):
            table[0][i] = 1
            
        for i in range(1,m):
            for j in range(1,n):
                table[i][j] = table[i-1][j] + table[i][j-1]
        return table[m-1][n-1]

64. Minimum Path Sum

动态规划求解,2333,贼烦。

class Solution(object):
    def minPathSum(self, grid):
        """
        :type grid: List[List[int]]
        :rtype: int
        """
        table = [[0 for x in range(n)] for x in range(m)]
        for i in range(m):
            table[i][0] = 1
        for i in range(n):
            table[0][i] = 1
            
        for i in range(1,m):
            for j in range(1,n):
                table[i][j] = table[i-1][j] + table[i][j-1]
        return table[m-1][n-1]

70. Climbing Stairs

斐波那契数列问题。

class Solution(object):
    def climbStairs(self, n):
        """
        :type n: int
        :rtype: int
        """
        if n == 1:
            return 1
        if n == 2:
            return 2
        m1 = 1
        m2 = 2
        for i in range(2,n):
            temp = m2
            m2 = m2 + m1
            m1 = temp
        return m2

72. Edit Distance

编辑距离

class Solution(object):
# O(m*n) space
    def minDistance(self, word1, word2):
        l1, l2 = len(word1)+1, len(word2)+1
        dp = [[0 for _ in xrange(l2)] for _ in xrange(l1)]
        for i in xrange(l1):
            dp[i][0] = i
        for j in xrange(l2):
            dp[0][j] = j
        for i in xrange(1, l1):
            for j in xrange(1, l2):
                dp[i][j] = min(dp[i-1][j]+1, dp[i][j-1]+1, dp[i-1][j-1]+(word1[i-1]!=word2[j-1]))
        return dp[-1][-1]

75. Sort Colors

其实就是对列表进行排序

# 36ms
# 11.6Mb
class Solution(object):
    def sortColors(self, nums):
        nums.sort()

遍历一次list,遇到0就把他插入到list的第一个位置,遇到2就把他插入到list的最后位置

# 32ms
# 11.7Mb
class Solution(object):
    def sortColors(self,nums):
        n = len(nums)
        index = 0
        index2 = 0
        while index < n-index2:
            if nums[index]==0:
                nums.pop(index)
                nums.insert(0,0)
                index += 1
            elif nums[index]==2:
                nums.pop(index)
                nums.append(2)
                index2 += 1
            else:
                index += 1

76. Minimum Window Substring

from collections import Counter
class Solution(object):
    def minWindow(self,s ,t):
    	# 建立一个字典,保存每个字符出现的次数
        dict_t = Counter(t)
        # 需要满足的次数,即非重复的字符数
        required = len(dict_t)
		# 记录当前窗口满足的条件数,
        formed = 0
        left, right = 0,0
        # ans是一个tuple,记录字符串子字符串长度和起始点
        ans = float('inf'),0,0
        
        # 当前窗口的字符的频率的统计
        window_count = {}
        while right < len(s):
            
            char = s[right]
            window_count[char] = window_count.get(char,0) + 1
            # 如果满足以下条件,满足的条件数即加1
            if char in window_count and window_count[char] == dict_t[char]:
                formed += 1
            # 如果条件均满足那么缩减窗口大小
            while left <= right and formed == required:
                char = s[left]
                # 替换窗口长度,取最小值
                if right - left + 1 < ans[0]:
                    ans = right - left + 1,left,right
                window_count[char] -= 1
                # 如果去掉一个字符后,依然满足条件,继续进行,如果不满足条件将formed-1
                if char in dict_t and window_count[char] < dict_t[char]:
                    formed -= 1
                left += 1
            right += 1
        return "" if ans[0] == float("inf") else s[ans[1] : ans[2] + 1]
        

78. 子集

循环: 遍历nums,然后遍历result,将reuslt的每一个list和nums里面的元素做拼接。nums每增加一个新元素,都对result中的元素进行拼接,然后和初始的result拼接在一起。 O ( n ) O(n) O(n)

def subsets(self, nums):
# 36ms
# 11.7Mb
    result = [[]]
    for num in nums:
        result += [item + [num] for item in result]
    return result

DFS:

class Solution(object):
    def subsets(self, nums):
        res = []
        self.dfs(sorted(nums), 0, [], res)
        return res

    def dfs(self, nums, start, path, res):
        res.append(path)
        for i in range(start, len(nums)):
            self.dfs(nums, i+1, path+[nums[i]], res)
class Solution(object):
    def subsets(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        self.result = []
        self.generate(nums,[],0)
        return self.result
    
    def generate(self,nums,item,index):
        if index == len(nums):
            self.result.append(item)
            return
        
        self.generate(nums, item+[nums[index]], index+1)
        self.generate(nums, item, index+1)

84. Largest Rectangle in Histogram

暴力法求所有的子间隔的面积,然后求最大值。

    def largestRectangleArea(self, heights):
        """
        :type heights: List[int]
        :rtype: int
        """
        length = len(heights)
        left,right = 0,length
        maxarea = 0
        
        for i in range(length):
            for j in range(i+1, length+1):
                area = min(heights[i:j]) * (j-i)
                maxarea = max(area, maxarea)
        return maxarea

依然看不太懂,思路明白但是实现方式不太懂,对于栈的一些知识不太了解。
https://blog.csdn.net/Zolewit/article/details/88863970

def largestRectangleArea(self, height):
    height.append(0)
    stack = [-1]
    ans = 0
    for i in xrange(len(height)):
        while height[i] < height[stack[-1]]:
            h = height[stack.pop()]
            w = i - stack[-1] - 1
            ans = max(ans, h * w)
        stack.append(i)
    height.pop()
    return ans

86.分割链表:

巧用临时结点,设置两个链表分别保存大于和小于x的结点。然后将两个临时结点连接起来。

class Solution:
# 36ms 89.86%
# 11.7 MB 38.12% 
    def partition(self, head, x):
        if head == None or head.next == None:
            return head

        cur = head
        pre_min = cur_min = ListNode(-1)
        pre_max = cur_max = ListNode(-1)

        while cur != None:
            if cur.val < x:
                cur_min.next = cur
                cur_min = cur_min.next
            else:
                cur_max.next = cur
                cur_max = cur_max.next

            cur = cur.next
        cur_min.next = pre_max.next
        cur_max.next = None
        return pre_min.next

90.子集II:

循环: 和78题类似,只不过在增加新的子集的时候判断是否在已知的里面,这可以解决同序重复问题([1,2,2],[1,2,2])。排序后可以解决不同序重复问题([1,2,2],[2,1,2])。

class Solution(object):
    def subsetsWithDup(self, nums):
        result = [[]]
        for num in sorted(nums):
            result += [i+[num] for i in result if i+[num] not in result]
        return result

94. Binary Tree Inorder Traversal

递归方法实现:

class Solution(object):
    def inorderTraversal(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        ans=[]
        if root==None:
            return ans
        def dfs(root):
            if root==None:
                return
            dfs(root.left)
            ans.append(root.val)
            dfs(root.right)
            return
        dfs(root)
        return ans

非递归方法:

class Solution(object):
    def inorderTraversal(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        #非递归方法
        stack=[]
        ans=[]
        while(root or stack):
            while(root):
                stack.append(root)
                root=root.left
            root=stack.pop()
            ans.append(root.val)
            root=root.right
        return ans

102. 二叉树的层次遍历:

用queue依次保存树的结点,向下遍历,依次保存每层的结点。每次遍历一次queue,相当于遍历依次上一层的所有结点,遍历一个结点便取出一个结点,直到queue为空为止。

class Solution(object):
    def levelOrder(self, root):

        if root is None:
            return
        queue=[root]
        res=[]
        while queue:
            tem=[]
            for i in range(len(queue)):
                cur_node = queue.pop(0)
                tem.append(cur_node.val)
                
                if cur_node.left is not None:
                    queue.append(cur_node.left)

                if cur_node.right is not None:
                    queue.append(cur_node.right)
            res.append(tem)
        return res

104.二叉树的最大深度:

递归,寻找递归关系。如果根节点不为空,那么返回两颗子树最大深度的最大值然后加1.

class Solution(object):
    def maxDepth(self, root):
        if root == None:
            return 0
        return max(self.maxDepth(root.left), self.maxDepth(root.right)) + 1

111. 二叉树的最小深度:

利用递归,如果根节点为空那么返回o。如果左右子树一个为空,返回另一个子树的mindepth同时+1.如果左右子树均不为空,则返回两棵树min(mindepth1, mindepth2) + 1

class Solution:
    # @param root, a tree node
    # @return an integer    
    def minDepth(self, root):
        if root == None:
            return 0
        if root.left==None or root.right==None:
            return self.minDepth(root.left)+self.minDepth(root.right)+1
        return min(self.minDepth(root.right),self.minDepth(root.left))+1

114.二叉树展开成链表:

保存在list中然后链接成链表:前序遍历保存每个结点,然后将结点相连。

class Solution(object):
    def preorder(self,root,result):
        if root == None:
            return 
        result.append(root)
        self.preorder(root.left, result)
        self.preorder(root.right, result)
        return result
    
    def flatten(self, root):
        if root == None:
            return []
        result = []
        result = self.preorder(root, result)
        for index in range(1,len(result)):
            result[index-1].left = None
            result[index-1].right = result[index]
        return result

inplace变换:

121.Best Time to Buy and Sell Stock:

使用暴力法进行遍历,后面的和前面比。

class Solution(object):
    def maxProfit(self, prices):
        """
        :type prices: List[int]
        :rtype: int
        """
        max_sum = 0
        length = len(prices)
        for i in range(length-1):
            for j in range(i+1, length):
                max_sum = max(max_sum, prices[j]-prices[i])
        return max_sum

遍历依次列表,保存一直到当前数值,遇到的最小值,用遍历的值减去最小值,求最大。相当于求每个值和前面最小值的差(这个值通过遍历依次保存),然后求这个差的最大值。

class Solution(object):
    def maxProfit(self, prices):
        """
        :type prices: List[int]
        :rtype: int
        """
        maxsum = 0
        length = len(prices)
        minprice = 1e10
        
        for num in prices:
            if num < minprice:
                minprice = num
            maxsum = max(maxsum, num-minprice)
        return maxsum

122. Best Time to Buy and Sell Stock II

暴力法,太复杂。
一次遍历,我们应该保存每一次相邻的波峰和波谷,多个相邻的波峰和波谷的差求和,要大于最优的选择(上题的最优解)。最极端的例子是12345类似的连续的序列,多个波峰波谷求和和最优单解相同。
在这里插入图片描述

class Solution(object):
    def maxProfit(self, prices):
        """
        :type prices: List[int]
        :rtype: int
        """
        if prices == []:
            return 0
        i,valley,peak = 0,prices[0],prices[0]
        maxprofit = 0
        length = len(prices)

        while i < length -1:
            # 如果当前值大于下一个值就一直往前走,找波谷
            while i < length - 1 and prices[i] >= prices[i+1]:
                i += 1
            valley = prices[i]

            # 如果当前值小于下一个值就一直走,找波峰
            while i < length - 1 and prices[i] <= prices[i+1]:
                i += 1
            peak = prices[i]

            maxprofit += peak - valley
            print(maxprofit)
        return maxprofit

128. Longest Consecutive Sequence

暴力法,排序后然后依次遍历。注意边界情况nums为空。注意去重,存在重复值排序后会存在bug。

class Solution(object):
    def longestConsecutive(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        if len(nums) == 0:
            return 0
        nums = sorted(set(nums))
        maxlen = 1
        temp = 1
        for i in range(len(nums)-1):
            if nums[i+1] - nums[i] == 1:
                temp += 1
            else:
                temp = 1
            maxlen = max(temp, maxlen)
        return maxlen

将序列保存成一个set(python的查找复杂度是 O ( 1 ) O(1) O(1)),找到连续序列开头的第一个值,然后依次判断后面的值是否在nums里面。

class Solution(object):
    def longestConsecutive(self, nums):
        maxlen = 0
        nums = set(nums)
        for num in nums:
        # 找到连续序列开头的第一个值
            if num-1 not in nums:
                cur_num = num
                cur_len = 1
                # 求后面序列的长度,这一步判断是O(1)
                while cur_num + 1 in nums:
                    cur_num += 1
                    cur_len += 1
                maxlen = max(maxlen, cur_len)
        return maxlen

136.Single Number

**哈希表:**保存每个数出现的次数;

class Solution(object):
    def singleNumber(self, nums):
        num_count = {}
        for num in nums:
            num_count[num] = num_count.get(num,0) + 1
        for key,value in num_count.items():
            if value == 1:
                return key

位操作: 一个数和0异或是他本身,两个相同的数异或是0;

class Solution(object):
# 100ms
    def singleNumber(self, nums):
        a = 0
        for i in nums:
            a ^= i
        return a

数学: 很秀的操作:

return 2 * sum(set(nums)) - sum(nums)

137.只出现一次的数字 II

**哈希表:**保存每个数出现的次数,这个操作和上题一样。

class Solution(object):
    def singleNumber(self, nums):
        num_count = {}
        for num in nums:
            num_count[num] = num_count.get(num,0) + 1
        for key,value in num_count.items():
            if value == 1:
                return key

数学: 依然是骚操作;

return (3*sum(set(nums)) - sum(nums))//2

138. 复制带随机指针的链表:

141. Linked List Cycle

奇葩值: 判断链表中是否有环,将链表中的元素设为某个奇葩值,如果链表元素会等于这个奇葩值,那么就是有环;

class Solution(object):
# 44ms
    def hasCycle(self, head):
        while head:
            if head.val == 'like':
                return True
            else:
                head.val = 'like'
            head = head.next
        return False

快慢指针: 建立两个指针,快指针和慢指针,快指针在前面,如果快指针后来超过了慢指针那么就是有环的,否则没有;

class Solution(object):
    def hasCycle(self, head):
        if head == None or head.next == None:
            return False
        slow = head
        fast = head.next
        while slow != fast:
            if fast == None or fast.next == None:
                return False
            slow = slow.next
            fast = fast.next.next
        return True

建立set保存结点:遍历结点如果该结点在set中出现过么肯定有环。

class Solution(object):
# 88ms
    def hasCycle(self, head):
        node_set = set()
        while head:
            if head not in node_set:
                node_set.add(head)
            else:
                return True
            head = head.next
        return False

142. Linked List Cycle II

建立一个哈希表保存链表中已经出现的结点,如果结点出现重复则判定为循环节。2333字典的查找速度要快于set????

class Solution(object):
# 60ms
    def detectCycle(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        unique_dict = {}
        while head:
            if head in unique_dict:
                return head
            unique_dict[head] = ''
            head = head.next
        
class Solution(object):
# 64ms
    def detectCycle(self, head):
        head_set = set()
        while head:
            if head in head_set:
                return head
            else:
                head_set.add(head)
                head = head.next

方法二:详细解释 + python实现 设置快慢指针,如果存在环那么两个指针肯定会相遇,设相遇点是meet。可通过数学方法证明,一个从head(头)出发,一个从meet(相遇点)出发,他们的相遇点即环的起点。

class Solution(object):
    def detectCycle(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        try:
            fast = head.next.next
            slow = head.next
            while fast != slow:
                slow = slow.next
                fast = fast.next.next
        except:
            return None
        slow = head
        while slow != fast:
            slow = slow.next
            fast = fast.next
        return slow

152.Maximum Product Subarray

暴力法:

class Solution(object):
    def maxProduct(self, nums):
        maxProd = -1e10
        for i in range(len(nums)):
            for j in range(i+1, len(nums)+1):
                temp = 1
                for k in range(i,j):
                    temp *= nums[k]
                maxProd = max(maxProd, temp)
        return maxProd

从前到后遍历,依次乘积的结果保存在list中相应的位置,主要解决的是0和负数的问题。最大值的情况,一定是从两头开始的,所以需要两头都需要考虑。

class Solution(object):
    def maxProduct(self, A):
        """
        :type nums: List[int]
        :rtype: int
        """
        B = A[::-1]
        for i in range(1,len(A)):
            A[i] *= A[i-1] or 1
            B[i] *= B[i-1] or 1
        return max(max(A),max(B))  

155.Min Stack

求得栈的最小值,时间复杂度是O(1) O(1)O(1)。建立一个辅助栈,每增加一个数,保存目前所有数的最小值在辅助栈的栈顶。
注意:辅助栈(minStack)何时入栈,出栈的时候注意边界值。

class MinStack(object):
# 运行时间:23ms
# 占用内存:5752k
    def __init__(self):
        self.stack = []
        self.minStack = []
        
    def push(self, node):
        # write code here
        self.stack.append(node)
        if self.minStack == [] or node < self.getMin():
            self.minStack.append(node)
        else:
            temp = self.getMin()
            self.minStack.append(temp)
        
    def pop(self):
        # write code here
        if self.stack == None or self.minStack == None:
            return None
        self.minStack.pop()
        self.stack.pop()
        
    def top(self):
        # write code here
        return self.stack[-1]
        
    def getMin(self):
        # write code here
        return self.minStack[-1]

160.Intersection of Two Linked Lists

建立set,然后将链表A结点均保存在set中,遍历链表B,返回在set中的第一个结点,如果没有返回None:

class Solution(object):
# 276ms 67.05% 
# 42mb 
    def getIntersectionNode(self, headA, headB):
        head_set = set()
        while headA:
            head_set.add(headA)
            headA = headA.next
            
        while headB:
            if headB in head_set:
                return headB
            headB = headB.next
        return None

求两个链表的长度,然后求其链表长度差,两个链表补齐后,遍历两个链表直到两个链表相等,即可返回,否则返回None。

class Solution(object):
    def get_length(self, head):
        # 求链表长度
        length = 0
        while head:
            length += 1
            head = head.next
        return length
    
    def getIntersectionNode(self, headA, headB):
        if headA == None or headB == None:
            return None
        lenA = self.get_length(headA)
        lenB = self.get_length(headB)
        
        diff = abs(lenB - lenA)
        
        if lenB > lenA:
            for _ in range(diff):
                headB = headB.next
        else:
            for _ in range(diff):
                headA = headA.next
        
        for _ in range(min(lenA,lenB)):
            if headA == headB:
                return headA
            headA = headA.next
            headB = headB.next
        
        return None

直到两个相等,否则一直遍历。

class Solution:
    def getIntersectionNode(self, headA, headB):
        if headA is None or headB is None:
            return None

        pa = headA # 2 pointers
        pb = headB

        while pa is not pb:
            # if either pointer hits the end, switch head and continue the second traversal, 
            # if not hit the end, just move on to next
            pa = headB if pa is None else pa.next
            pb = headA if pb is None else pb.next

        return pa # only 2 ways to get out of the loop, they meet or the both hit the end=None

169.求众数:

出现次数超过一半的数;
排序: 对原list排序后返回中间的数。

class Solution(object):
    def majorityElement(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        nums = sorted(nums)
        return nums[len(nums)//2]

哈希表: 遍历list然后将次数保存在哈希表。时间: O ( n ) O(n) O(n); 空间: O ( n ) O(n) O(n)

class Solution(object):
    def majorityElement(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        num_count = {}
        for num in nums:
            num_count[num] = num_count.get(num,0) + 1
        length = len(nums)//2
        for key,value in num_count.items():
            if value > length:
                return key
        return -1

加减法: 因为肯定有一个数超过一半,用count来进行计数,如果下一个值和之前保留的值相同那么+1,否则-1,最后留下的一定是超过一半的数;时间 O ( n ) O(n) O(n);空间 O ( 1 ) O(1) O(1)

class Solution:
    def majorityElement(self, nums):
        count = 0
        result = None
        for num in nums:
            if count == 0:
                result = num
            count += (1 if result == num else -1)
        return result

198.打家劫舍:

采用递归求解,判断好结束条件,然后写递推公式即可,但是超时。

class Solution(object):
    def rob(self, nums):
        if len(nums) == 0:
            return 0
        if len(nums) <= 2:
            return max(nums)
        
        num2 = nums[1]
        num1 = nums[0] + self.rob(nums[2:])
        if len(nums) >= 4:
            num2 += self.rob(nums[3:])
                                  
        return max(num1, num2)

采用动态规划,依然不是很懂,解法.

class Solution:
    # @param num, a list of integer
    # @return an integer
    def rob(self, num):
        max_3_house_before, max_2_house_before, adjacent = 0, 0, 0
        for cur in num:
            max_3_house_before, max_2_house_before, adjacent = \
            max_2_house_before, adjacent, max(max_3_house_before+cur, max_2_house_before+cur)
        return max(max_2_house_before, adjacent)

200. 岛屿的个数:

class Solution():
    def numIslands(self, grid):
        def sink(i, j):
            if 0 <= i < len(grid) and 0 <= j < len(grid[i]) and grid[i][j] == '1':
                grid[i][j] = '0'
                map(sink, (i+1, i-1, i, i), (j, j, j+1, j-1))
                return 1
            return 0
        return sum(sink(i, j) for i in range(len(grid)) for j in range(len(grid[i])))

206.反转链表:

原链表的的第一个值的next必然是None,所以首先设一个链表为None(返回的答案)。然后依次遍历head,将head保存在prev里面,同时将prev的next指向prev,利用了python能同时赋值的特性,不必再设置别的变量来保存prev。这是最简单的写法,分开写比较麻烦。

class Solution(object):
    def reverseList(self, head):
        prev = None
        while head:
            prev,prev.next,head = head,prev,head.next
        return prev

分开写:

class Solution(object):
    def reverseList(self, head):
        prev = None
        while head:
            temp = head.next
            head.next = prev
            prev = head
            head = temp
        return prev   

208.实现前缀树:

直接实现即可,建立一个list,然后完成相应的功能。

class Trie(object):
    def __init__(self):
        """
        Initialize your data structure here.
        """
        self.trie =[]
        
    def insert(self, word):
        """
        Inserts a word into the trie.
        :type word: str
        :rtype: None
        """
        self.trie.insert(0,word)
        
    def search(self, word):
        """
        Returns if the word is in the trie.
        :type word: str
        :rtype: bool
        """
        if word in self.trie:
            return True
        else:
            return False

    def startsWith(self, prefix):
        """
        Returns if there is any word in the trie that starts with the given prefix.
        :type prefix: str
        :rtype: bool
        """
        length = len(prefix)
        flag = False
        for strings in self.trie:
            if prefix == strings[:length]:
                flag = True
        return flag

215.数组中的第k个最大元素

作弊操作,调用内部函数。应该自己写快排尝试解决。

class Solution(object):
# 72 ms
# 12.2Mb
    def findKthLargest(self, nums, k):
        return sorted(nums)[-k]  

222.完全二叉树的节点:

利用递归,只要建立好递推关系式和终止条件,其他都好说。

class Solution(object):
    def countNodes(self, root):
        if root == None:return 0
        return self.countNodes(root.left) + self.countNodes(root.right) + 1

226.翻转二叉树

通过递归来实现,对左子树和右子树执行相同的操作,然后交换左右子树。

class Solution(object):
# 32 ms
# 11.8Mb
    def invertTree(self, root):
        if root == None:
            return None

        if root.left != None:
            root.left = self.invertTree(root.left)
        if root.right != None:
            root.right = self.invertTree(root.right)

        root.right,root.left = root.left,root.right
        return root

232.用栈实现队列:

2333直接用list实现的,貌似作弊?

class MyQueue(object):

    def __init__(self):
        """
        Initialize your data structure here.
        """
        self.queue = []

    def push(self, x):
        """
        Push element x to the back of queue.
        :type x: int
        :rtype: None
        """
        self.queue.append(x)
        

    def pop(self):
        """
        Removes the element from in front of queue and returns that element.
        :rtype: int
        """
        return self.queue.pop(0)
        

    def peek(self):
        """
        Get the front element.
        :rtype: int
        """
        return self.queue[0]
        

    def empty(self):
        """
        Returns whether the queue is empty.
        :rtype: bool
        """
        return self.queue == []

234.回文链表:

class Solution(object):
# 96 ms 
# 31.6Mb
    def isPalindrome(self, head):
        """
        :type head: ListNode
        :rtype: bool
        """
        list1 = []
        while head:
            list1.append(head.val)
            head = head.next
        
        for i in range(len(list1)//2):
            if list1[i] != list1[len(list1)-1-i]:
                return False
        return True

238.Product of Array Except Self

重点是统计0的个数。没有0,用除法即可。有一个0,那么有一个数不为0,其他均为0。有两个及以上的0,所有都是0.

class Solution(object):
    def productExceptSelf(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        zeroNum = 0
        product = 1
        for num in nums:
            if num == 0:
                zeroNum += 1
            else:
                product *= num
        for i in range(len(nums)):
            if nums[i] == 0 and zeroNum == 1:
                nums[i] = product
            elif zeroNum == 0:
                nums[i] = product/nums[i]
            else:
                nums[i] = 0
        return nums

little trick,从左到右遍历,保存每个数前面所有的数的乘积。从右到左遍历,相当于保存这个数后面所有数的乘积。所有遍历两次数组,即可求出当前这个数前面所有数和后面所有数的乘积。

class Solution:
    # @param {integer[]} nums
    # @return {integer[]}
    def productExceptSelf(self, nums):
        p = 1
        n = len(nums)
        output = []
        for i in range(n):
            output.append(p)
            p = p * nums[i]
        p = 1
        for i in range(n-1,-1,-1):
            output[i] = output[i] * p
            p = p * nums[i]
        return output

239.滑动窗口最大值

遍历即可,时间复杂度是 O ( k n ) O(kn) O(kn)

class Solution(object):
    def maxSlidingWindow(self, nums, k):
        if len(nums) == 0 or k == 0:
            return []
        result = []
        for i in range(len(nums) - k+1):
            result.append(max(nums[i:i+k]))
        return result

240.搜索二维矩阵 II:

暴力法直接遍历:

class Solution(object):
    def searchMatrix(self, matrix, target):
        for i in range(len(matrix)):
            for j in range(len(matrix[0])):
                if matrix[i][j] == target:
                    return True
        return False

矩阵是每行的元素从左到右升序排列。每列的元素从上到下升序排列。所以可以从右上到左下遍历,如果matrix[i][j]小于这个target,那么i加1,大于target则j减1。

class Solution(object):
# 76 ms  62.66%
# 15.7Mb
    def searchMatrix(self, matrix, target):

        if len(matrix) == 0 or len(matrix[0]) == 0:
            return False
        i,j = 0,len(matrix[0])-1
        while i < len(matrix) and j >= 0:
            
            if matrix[i][j] == target:
                return True
            elif matrix[i][j] < target:
                i += 1
            elif matrix[i][j] > target:
                j -= 1
        return False

264.丑数:

判断一个2,3,5是否是它的因子(通过取余来实现),如果是他的因子那么除以2,3,5。在num变成1之前,如果2,3,5均不是他的因子,那么不是丑数,如果最后得到1便是丑数。

class Solution(object):
    def isUgly(self, num):
        divids = [2,3,5]
        while num != 1:
            prev = num
            for divid in divids:
                if num%divid == 0:
                    num = num/divid
                    break
            if num == prev:
                return False
        return True

同样的思路,判断是不是2,3,5的倍数,如果是的话就除以这个因子,但是代码明显更秀。

class Solution(object):
    def isUgly(self, num):
        if num == 0:
            return False
        while num%2 == 0:num /= 2
        while num%3 == 0:num /= 3
        while num%5 == 0:num /= 5
        return num == 1

265.丑数II:

依次生成,将生成的丑数保存在ugly_set中,每次取最小的一个作为下一个丑数,然后将这个丑数在ugly_set去掉,result*2,3,5的每一个值依次保存在ugly_set中。

class Solution(object):
    def nthUglyNumber(self, n):
        if n == 0:
            return 0
        count = 1
        ugly_set = set()
        result = 1
        while count < n:
            ugly_set.add(result*2)
            ugly_set.add(result*3)
            ugly_set.add(result*5)
            result = min(ugly_list)
            count += 1
            ugly_list.remove(result)
        return result

284.移动零:

遍历遇到0就remove,然后在末尾添新的0。

class Solution(object):
    def moveZeroes(self, nums):
        for num in nums:
            if num == 0:
                nums.remove(0)
                nums.append(0)
        return nums

287.寻找重复数

排序,然后判断两个相邻的数是否相等,如果相等那么是重复的: O ( n l o g n ) O(nlogn) O(nlogn)。空间复杂度0.

class Solution:
    def findDuplicate(self, nums):
        nums.sort()
        for i in range(1, len(nums)):
            if nums[i] == nums[i-1]:
                return nums[i]

哈希表保存次数: O ( n ) O(n) O(n),空间复杂度较高。

class Solution(object):
# 84ms 38.32% 
# 14.9Mb 5.09%
    def findDuplicate(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        count = {}
        for num in nums:
            count[num] = count.get(num,0) + 1
        for num in nums:
            if count[num] > 1:
                return num
        return None 

采用set保存已经出现过的数,比上一种更快。

    def findDuplicate(self, nums):
        seen = set()
        for num in nums:
            if num in seen:
                return num
            seen.add(num)

409.Longest Palindrome

统计字符串中每个字符的出现的次数,如果次数为偶数,直接相加,奇数除以2取整。count/2*2

# 28ms
# 11.6Mb
class Solution:
    def longestPalindrome(self, s):
        ans = 0
        for v in collections.Counter(s).values():
            ans += int(v / 2) * 2
            if ans & 1 == 0 and v & 1 == 1:
                ans += 1
        return ans

438. 找到字符串中所有字母异位词

暴力做法,遍历所有字符串

class Solution(object):
    def findAnagrams(self, s, p):
        """
        :type s: str
        :type p: str
        :rtype: List[int]
        """
        result = []
        len_p = len(p)
        for i in range(len(s)-len_p+1):
            if sorted(s[i:i+len_p]) == sorted(p):
                result.append(i)
        return result

448.找到所有数组中消失的数字:

保存完整数组,然后遍历。

class Solution(object):
# 464 ms,73.91%
    def findDisappearedNumbers(self, nums):
        result = []
        nums2 = list(range(1,len(nums)+1))
        nums = set(nums)
        return [num for num in nums2 if num not in nums]

461.汉明距离:

异或然后求其二进制中1的个数直接判断。

class Solution(object):
    def hammingDistance(self, x, y):
        result = x^y
        count = 0
        for i in str(bin(result)):
            if i == '1':
                count += 1
        return count

494. 目标和

DFS

581.最短无序连续子数组:

对原数组进行排序,比较排好序的数组和原数组的差别,第一位不同的便是最短无序子数组的头;倒序遍历,第一个不同的便是尾。

class Solution(object):
# 264ms 32.54%
    def findUnsortedSubarray(self, nums):
        nums2 = sorted(nums)
        for i in range(len(nums)):
            if nums[i] != nums2[i]:
                start = i
                break
        for i in range(len(nums)-1, -1,-1):
            if nums[i] != nums2[i]:
                end = i
                break
        try:
            return end-start+1
        except:
            return 0

617.合并二叉树:

采用递归,将第二颗二叉树额值依次加到第一棵树上面,如果某一个棵树为None则返回另一颗树。确定根节点后,依次再向下考虑左右叶子结点。

class Solution(object):
# 84 ms # 59.6%

    def mergeTrees(self, t1, t2):
        if t1 == None:
            return t2
        if t2 == None:
            return t1

        t1.val += t2.val
        
        t1.left = self.mergeTrees(t1.left, t2.left)
        t1.right = self.mergeTrees(t1.right, t2.right)
        return t1

647. Palindromic Substrings

暴力做法,确定每一个子字符串是否是回文字符串,然后统计个数

class Solution(object):
    def countSubstrings(self, s):
        """
        :type s: str
        :rtype: int
        """
        count = 0
        def IsPalin(strs):
        # 判断一个字符串是否是回文字符串,头和尾比较
            for i in range(int(len(strs)/2)):
                if strs[i] != strs[-i-1]:
                    return False
            return True
        def IsPalin2(strs):
        # 判断是否是回文,翻转字符串判断是否相等
            if strs[::-1] == strs:
                return True
            return False
        
        for i in range(len(s)):
            for j in range(i+1, len(s)+1):
                if IsPalin(s[i:j]):
                    count += 1
        return count     

遍历字符串,以每个字符为中心,向两边展开,判断每个新加入的字母是否相等。

class Solution(object):
    def countSubstrings(self, s):
        """
        :type s: str
        :rtype: int
        """
        count = 0
        for i in range(len(s)):
            start,end = i,i
            while(start >= 0 and end < len(s) and s[start] == s[end]):
                start -= 1
                end += 1
                count += 1
            start,end = i,i+1
            while(start >= 0 and end < len(s) and s[start] == s[end]):
                start -= 1
                end += 1
                count += 1
        return count

771. Jewels and Stones

class Solution(object):
    def numJewelsInStones(self, J, S):
        """
        :type J: str
        :type S: str
        :rtype: int
        """
        return sum([1 if i in J else 0 for i in S])
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

linxid

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值