LeetCode刷题笔记 - Algorithms - Easy - Python

按Frequency的顺序刷。斜体重点或未掌握。


05/20/2022

1)1. Two Sum
Input: nums = [2,7,11,15], target = 9
Output: [0,1]
Explanation: Because nums[0] + nums[1] == 9, we return [0, 1].
思路:用字典(hashmap)存已经遍历过的数字,就不用再遍历一次了。=。每经过一个数字n,去字典里找target-n, 在就返回,不在就将n存入字典。

2)680. Valid Palindrome II
Given a string s, return true if the s can be palindrome after deleting at most one character from it. 删除至多一个字母,判断剩下的字符串是不是回文。
思路:2 pointers, i从头开始,j从尾开始,如果s[i]!=s[j],检查s[i:j]和s[i+1,j+1]是不是回文,如果都不是,return False;如果有一个是,return True.

3)20. Valid Parentheses
Input: s = "()[]{}" Output: true
Input: s = "(]" Output: false
思路:建立hashmap . mapping = {")": "(", "}": "{", "]": "["}. 建一个空List作为stack, 开始遍历,如果是一个openning bracket, 就push到stack里(append to list); 如果是closing bracket, 和stack最顶上的元素(就是最近一个被append到list的元素,stack.pop())对比,不一致就return False. 直到遍历完所有元素,stack应为空。
note: list l.pop()弹出最后一个元素,l.pop(i)弹出第i个元素

4)13. Roman to Integer
罗马数字转数字
思路:建立mapping
values = {"I": 1, "V": 5, "X": 10, "L": 50, "C": 100, "D": 500, "M": 1000, "IV": 4, "IX": 9, "XL": 40, "XC": 90, "CD": 400, "CM": 900}

5)121. Best Time to Buy and Sell Stock
Input: prices = [7,1,5,3,6,4]
Output: 5
Explanation: Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5. Note that buying on day 2 and selling on day 1 is not allowed because you must buy before you sell.
思路:建立minprice=float('inf')和maxprofit=0,开始遍历,价格比minprice低则更新minprice,价格-minprice>max_profit则更新max_profit。

6)53. Maximum Subarray
Input: nums = [-2,1,-3,4,-1,2,1,-5,4]
Output: 6
Explanation: [4,-1,2,1] has the largest sum = 6.
思路:动态规划,遍历列表的过程中更新两个变量,current_subarray=max(num, current_subarray + num),max_subarray = max(max_subarray, current_subarray)

7)408. Valid Word Abbreviation
A string can be abbreviated by replacing any number of non-adjacent, non-empty substrings with their lengths. The lengths should not have leading zeros.
Input: word = "internationalization", abbr = "i12iz4n"
Output: true
Explanation: The word "internationalization" can be abbreviated as "i12iz4n" ("i nternational iz atio n").
思路:分别遍历word和abbreviation,字母就比较,数字就先取到最大长度,再比较;或者用regular expression

8)14. Longest Common Prefix
find the longest common prefix string amongst an array of strings.
Input: strs = ["flower","flow","flight"]
Output: "fl"
思路:找到最短的一个string,每个字母与其他string的相同位置字母比较,直到出现不同。

9)938. Range Sum of BST
Given the root node of a binary search tree and two integers low and high, return the sum of values of all nodes with a value in the inclusive range [low, high].
思路:找到树上符合特定大小的所有数字的和。binary search tree的特点是左子节点比节点小,右子节点比节点大。Depth First Search,可以Recursive或Iterative。Recursive:

def rangeSumBST(self, root: Optional[TreeNode], low: int, high: int) -> int:
    def dfs(node):
        nonlocal ans
        if node:
            if low <= node.val <= high:
                ans += node.val
            if low < node.val:
                dfs(node.left)
            if node.val < high:
                dfs(node.right)

    ans = 0
    dfs(root)
    return ans

05/21/2022

10)9. Palindrome Number
回文数
思路:将数字转化成str,逐位判断;或通过不断%10,新建一个revertnumber,判断与原数是否相等。

11)704. Binary Search
数字从小到大排列的数组,用binary search的方法找到target数字的位置,不存在则return -1.
思路:设置三个变量,left,pivot,right (lower,point,upper),二分法不断缩小范围。

12)1207. Unique Number of Occurrences
Given an array of integers arr, return true if the number of occurrences of each value in the array is unique, or false otherwise.
思路:创建字典

def uniqueOccurrences(self, arr: List[int]) -> bool:
    freq_dict={a:arr.count(a) for a in arr}
    freq_list=freq_dict.values()
    return len(freq_list)==len(set(freq_list))

13)716. Max Stack
Design a max stack data structure that supports the stack operations and supports finding the stack's maximum element.
思路:答案是Two Stacks,存储数组(x, m),x是push进来的数字,m是当前的最大值。但是我list只存x不存m也通过了?

14)696. Count Binary Substrings
Give a binary string s, return the number of non-empty substrings that have the same number of 0's and 1's, and all the 0's and all the 1's in these substrings are grouped consecutively.
思路:group连续数字,例如s = "110001111000000", then groups = [2, 3, 4, 6]. 两个group i-1和i 组合能得到min(groups[i-1], groups[i])种连续数组。

15)217. Contains Duplicate
返回list中是否包含重复。
思路:python里很简单,直接return len(nums)>len(set(nums))

16)415. Add Strings
Input: num1 = "11", num2 = "123"
Output: "134"
思路: 1.Python里很简单,return str(int(num1)+int(num2)); 2.利用unicode, ord(n) - ord('0'); 3.数学方法一位位算,进位carry

17)937. Reorder Data in Log Files
题干比较复杂
思路:
letters.sort(key = lambda x: x.split()[1]) #when suffix is tie, sort by identifier
letters.sort(key = lambda x: x.split()[1:]) #sort by suffix

18)346. Moving Average from Data Stream
不断输入新数字,求Moving Average
思路:可以建普通List作为queue,也可以用deque()。
Note: Deques are a generalization of stacks and queues (the name is pronounced deck and is short for double-ended queue).


05/22/2022

19)21. Merge Two Sorted Lists
You are given the heads of two sorted linked lists list1 and list2. Merge the two lists in a one sorted list.
思路:

  1. Recursive

     def mergeTwoLists(self, l1, l2):
       if l1 is None:
           return l2
       elif l2 is None:
           return l1
       elif l1.val < l2.val:
           l1.next = self.mergeTwoLists(l1.next, l2)
           return l1
       else:
           l2.next = self.mergeTwoLists(l1, l2.next)
           return l2
  2. Iterative

     def mergeTwoLists(self, l1, l2):
       prehead = ListNode(-1)
       prev = prehead
       while l1 and l2:
           if l1.val <= l2.val:
               prev.next = l1
               l1 = l1.next
           else:
               prev.next = l2
               l2 = l2.next            
           prev = prev.next
       prev.next = l1 or l2
       return prehead.next
    

20)412. Fizz Buzz
answer[i] == "FizzBuzz" if i is divisible by 3 and 5; "Fizz" if i is divisible by 3; "Buzz" if i is divisible by 5; i (as a string) if none of the above conditions are true.
思路:if else

21)88. Merge Sorted Array
two integer arrays nums1 and nums2, sorted in non-decreasing order, and two integers m and n, representing the number of elements in nums1 and nums2 respectively. Merge nums1 and nums2 into a single array sorted in non-decreasing order.
Input: nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
Output: [1,2,2,3,5,6]
Explanation: The arrays we are merging are [1,2,3] and [2,5,6].
The result of the merge is [1,2,2,3,5,6] with the underlined elements coming from nums1.
思路: Three Pointers, instead of start from the beginning, we start from the end. 从右边开始可以avoid overwriting numbers,降低space complexity from O(m) to O(1).

def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
    # Do not return anything, modify nums1 in-place instead.

    # Set p1 and p2 to point to the end of their respective arrays.
    p1 = m - 1
    p2 = n - 1

    # And move p backwards through the array, each time writing
    # the smallest value pointed at by p1 or p2.
    for p in range(n + m - 1, -1, -1):
        if p2 < 0:
            break
        if p1 >= 0 and nums1[p1] > nums2[p2]:
            nums1[p] = nums1[p1]
            p1 -= 1
        else:
            nums1[p] = nums2[p2]
            p2 -= 1

22)70. Climbing Stairs
爬楼梯,一次可以跨1步或2步,求n级楼梯的跨步方法数。
思路: dynamic programming, 相当于n-1级台阶的基础上跨1步,或者是n-2级台阶的基础上跨2步,return self.climbStairs(n-2)+self.climbStairs(n-1)。但是直接这样做会导致Time Limit Exceeded。所以建一个steps=[]列表,存入每一级的方法数,steps.append(steps[i-2]+steps[i-1])。

23)1507. Reformat Date
Input: date = "20th Oct 2052"
Output: "2052-10-20"
思路:建一个月份的mapping,写规则即可。

24)125. Valid Palindrome
去除所有空格和标点符号后,检查是否为回文数。
思路:2 pointers, i=0, j=len-1。s[i].isalnum()检查是否为alphanumeric, s[i].lower()转化为小写。

25)234. Palindrome Linked List
检查linked list是否回文
思路:可以遍历转化为list,或者recursive,但都是O(N)space.

Recursive:

def isPalindrome(self, head: ListNode) -> bool:
  self.front_pointer = head

  def recursively_check(current_node=head):
      if current_node is not None:
          if not recursively_check(current_node.next):
              return False
          if self.front_pointer.val != current_node.val:
              return False
          self.front_pointer = self.front_pointer.next
      return True

  return recursively_check()

Reverse Second Half In-place, 这个方法是O(1)space:

def isPalindrome(self, head: ListNode) -> bool:
    if head is None:
        return True

    # Find the end of first half and reverse second half.
    first_half_end = self.end_of_first_half(head)
    second_half_start = self.reverse_list(first_half_end.next)

    # Check whether or not there's a palindrome.
    result = True
    first_position = head
    second_position = second_half_start
    while result and second_position is not None:
        if first_position.val != second_position.val:
            result = False
        first_position = first_position.next
        second_position = second_position.next

    # Restore the list and return the result.
    first_half_end.next = self.reverse_list(second_half_start)
    return result    

def end_of_first_half(self, head):
    fast = head
    slow = head
    while fast.next is not None and fast.next.next is not None:
        fast = fast.next.next
        slow = slow.next
    return slow

def reverse_list(self, head):
    previous = None
    current = head
    while current is not None:
        next_node = current.next
        current.next = previous
        previous = current
        current = next_node
    return previous

26)605. Can Place Flowers
间隔插花,array中1表示已经有花,求能不能再插入n支,使花均不相邻。
Input: flowerbed = [1,0,0,0,1], n = 1
Output: true
Input: flowerbed = [1,0,0,0,1], n = 2
Output: false
思路: 中间位置,连续3个空格可以插1个,4个插1个,5个插2个,6个插2个...能插(n-1)//2个。两边比较特殊,可以在首尾分别插入0,就可以转化为中间的处理。遍历即可。

27)509. Fibonacci Number
斐波那契数列,F(0) = 0, F(1) = 1,F(n) = F(n - 1) + F(n - 2), for n > 1.
思路: 可以直接recursive, return self.fib(n-1)+self.fib(n-2), 但是这样慢, 可以建一个list把中间计算结果都存下来, fibs.append(fibs[i-2]+fibs[i-1])

28)706. Design HashMap
Design a HashMap without using any built-in hash table libraries.
思路: list中存数组。

29)387. First Unique Character in a String
Given a string s, find the first non-repeating character in it and return its index. If it does not exist, return -1.
思路: 1.先将每个字母出现的频率存到dict,再从头遍历,如果count=1就return当前位置。2.一个dict存字母和第一次出现的位置,一个set存见过的字母,如果见过就从dict中删除。

30)118. Pascal's Triangle

pascal[i][j] = pascal[i-1][j-1] + pascal[i-1][j]

31)359. Logger Rate Limiter
10s内不能输出相同的message
思路:创建dict:self.messages[message]=timestamp

32)697. Degree of an Array
数字出现的频率称为degree,找出包含最大degree的最短substring.
思路:dict

33)344. Reverse String
翻转字符串。
思路:2 pointers,不断交换两个字符。

def reverseString(self, s):
    left, right = 0, len(s) - 1
    while left < right:
        s[left], s[right] = s[right], s[left]
        left, right = left + 1, right - 1

34)1047. Remove All Adjacent Duplicates In String
循环删除字符串中相邻重复的字符
Input: s = "abbaca"
Output: "ca"
思路:
1.generate 26 possible duplicates: duplicates = {2 * ch for ch in ascii_lowercase}, for d in duplicates: S = S.replace(d, '')
2.Stack:空list,重复就把前一个pop

35)278. First Bad Version
你可以调用一个函数isBadVersion(n),来检查这个version有没有问题。假如3是好的,4和5是坏的,那么输出4。
思路:binary search

36)543. Diameter of Binary Tree
Given the root of a binary tree, return the length of the diameter of the tree.
The diameter of a binary tree is the length of the longest path between any two nodes in a tree. This path may or may not pass through the root.
思路: Depth-first Search

def diameterOfBinaryTree(self, root):
    self.ans = 0
    
    def depth(p):
        if not p: return 0
        left, right = depth(p.left), depth(p.right)
        self.ans = max(self.ans, left+right)
        return 1 + max(left, right)
        
    depth(root)
    return self.ans

37)349. Intersection of Two Arrays
求两个数组的交集。
思路:
1.Python直接return list(set(nums1) & set(nums2))
2.brute-force searching
3.字典记录第一个数组,对第二个数组check是否在字典中
4.两个数组分别排序,two pointers

38)206. Reverse Linked List
逆转链表
思路:
Iterative

def reverseList(self, head: ListNode) -> ListNode:
    prev = None
    curr = head
    while curr:
        next_temp = curr.next
        curr.next = prev
        prev = curr
        curr = next_temp            
    return prev

Recursive

def reverseList(self, head: ListNode) -> ListNode:
    if (not head) or (not head.next):
        return head
    p = self.reverseList(head.next)
    head.next.next = head
    head.next = None
    return p

39)724. Find Pivot Index
找到一个位置,位置左边所有数的和=右边所有数的和(不包括自己)
思路: Time: O(n),Space: O(1)

def pivotIndex(self, nums):
    left, right = 0, sum(nums)
    for index, num in enumerate(nums):
        right -= num
        if left == right:
            return index
        left += num
    return -1

40)283. Move Zeroes
move all 0's to the end of it while maintaining the relative order of the non-zero elements.
Input: nums = [0,1,0,3,12]
Output: [1,3,12,0,0]
思路: 2 pointers, Time: O(n),Space: O(1)

def moveZeroes(self, nums: list) -> None:
    slow = 0
    for fast in range(len(nums)):
        if nums[fast] != 0 and nums[slow] == 0:
            nums[slow], nums[fast] = nums[fast], nums[slow]
        # wait while we find a non-zero element to swap with you
        if nums[slow] != 0:
            slow += 1

你可能感兴趣的:(pythonleetcode)