算法刷题笔记

算法刷题

注:留意等于号跟在哪、是否要加1、特殊情况(前几个情况)
参考:
https://github.com/csujedihy/lc-all-solutions
https://space.bilibili.com/478428905/video

codetop

206.反转链表
口诀:while中等号右边对应下一行等号左边

class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        pre=None
        cur=head #定义双指针 
        while cur:
            tmp=cur.next #存储下一个点
            cur.next=pre #两个节点间逆序
            pre=cur #
            cur=tmp # 两个节点往前移动,cur会在pre前一个节点
        return pre

补充题4.快速排序
方法1:

class Solution:
    def sortArray(self, nums: List[int]) -> List[int]:
        def partition(nums, start, end):
            p = random.randrange(start, end + 1) # 注意这里+1
            pv = nums[p]
            nums[end], nums[p] = nums[p], nums[end]
            mid = start
            for i in range(start, end):
                if nums[i] <= pv:
                    nums[i], nums[mid] = nums[mid], nums[i]
                    mid += 1
            nums[mid], nums[end] = nums[end], nums[mid]
            return mid
        
        def quicksort(nums, start, end):
            if end - start <= 0:
                return # 注意这里什么也不return
            mid = partition(nums, start, end)
            quicksort(nums, start, mid - 1)
            quicksort(nums, mid + 1, end) 

        quicksort(nums,0,len(nums)-1) # 注意这里-1
        return nums

方法2:
两头找会更快,leetcode 中可以不 import random

class Solution:
    def sortArray(self, nums: List[int]) -> List[int]:
        import random                               #导入随机数函数库
        def quicksort(nums,left,right):
            flag=nums[random.randint(left,right)]   #随机初始化哨兵位置
            i,j=left,right                          #设定从左到右的指针i,从右到左的指针j
            while i<=j:
                while nums[i]<flag: i+=1            #i从左往右扫,找到大于等于flag的数。
                while nums[j]>flag: j-=1            #j从右往左扫,找到小于等于flag的数。
                if i<=j:
                    nums[i],nums[j]=nums[j],nums[i] #交换左右指针下标对应的数值
                    i+=1                            #左指针继续往右走
                    j-=1                            #右指针继续往左走
            if i<right: quicksort(nums,i,right)     #递归解决flag左边的低位数组的排序
            if j>left:  quicksort(nums,left,j)      #递归解决flag右边的低位数组的排序
        quicksort(nums,0,len(nums)-1)               #函数入口,将整个数组的信息传入
        return nums                                 #返回修改后的nums

21.合并两个有序链表

class Solution:
    def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
        if not list1: return list2  # 终止条件,直到两个链表都空
        if not list2: return list1
        if list1.val <= list2.val:  # 递归调用
            list1.next = self.mergeTwoLists(list1.next,list2) # 谁小了就谁.next,可以理解为list1后面的所有节点和list2全部接到list1.next后面
            return list1 # 改变了list1后的顺序,所以返回list1
        else:
            list2.next = self.mergeTwoLists(list1,list2.next) # self.mergeTwoLists中的list1和list2的顺序不能翻了
            return list2

53.最大子数组和

class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        if len(nums) == 0:
            return 0
        preSum = maxSum = nums[0]
        for i in range(1, len(nums)): # 共需存储两个值
            preSum = max(preSum + nums[i], nums[i]) # 当前连续子列是否要断开,可以拿[-2,1]简单理解,推广到更多项
            maxSum = max(maxSum, preSum) # 历史最大与当前最大对比
        return maxSum

415.字符串相加

class Solution:
    def addStrings(self, num1: str, num2: str) -> str:
        res = ""
        i, j, carry = len(num1) - 1, len(num2) - 1, 0
        while i >= 0 or j >= 0:
            n1 = int(num1[i]) if i >= 0 else 0
            n2 = int(num2[j]) if j >= 0 else 0
            tmp = n1 + n2 + carry
            carry = tmp // 10
            res = str(tmp % 10) + res
            i, j = i - 1, j - 1
        return "1" + res if carry else res

704.二分查找

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        left, right = 0, len(nums) - 1
        while left <= right:
            mid = (left + right) // 2
            if nums[mid] == target:
                return mid
            elif nums[mid] < target:
                left = mid + 1
            else:
                right = mid - 1
        return -1

8.字符串转为整数
解法1:

class Solution(object):
  def myAtoi(self, s):
    """
    :type str: str
    :rtype: int
    """
    s = s.strip()
    sign = 1
    if not s:
      return 0
    if s[0] in ["+", "-"]:
      if s[0] == "-":
        sign = -1
      s = s[1:]
    ans = 0
    for c in s:
      if c.isdigit():
        ans = ans * 10 + int(c)
      else:
        break
    ans *= sign
    if ans > 2147483647:
      return 2147483647
    if ans < -2147483648:
      return -2147483648
    return 

解法二:

class Solution:
    def myAtoi(self, s: str) -> int:
        return max(min(int(*re.findall('^[\+\-]?\d+', s.lstrip())), 2**31 - 1), -2**31)

正则表达式:

^:匹配字符串开头
[\+\-]:代表一个+字符或-字符
?:前面一个字符可有可无
\d:一个数字
+:前面一个字符的一个或多个
\D:一个非数字字符
*:前面一个字符的0个或多个

3.无重复字符串的最长子串
滑动窗口

def lengthOfLongestSubstring(self, s):
  d = {}
  start = 0
  ans = 0
  for i, c in enumerate(s):
    if c in d:
      start = max(start, d[c] + 1)
    d[c] = i
    ans = max(ans, i - start + 1)
  return ans

215.数组中的第K个最大元素
方法1:

import random


class Solution(object):
  def findKthLargest(self, nums, k):
    """
    :type A: List[int]
    :type k: int
    :rtype: int
    """

    def quickselect(start, end, nums, k):
      if start == end:
        return nums[start]

      mid = partition(start, end, nums)

      if mid == k:
        return nums[mid]
      elif k > mid:
        return quickselect(mid + 1, end, nums, k)
      else:
        return quickselect(start, mid - 1, nums, k)

    def partition(start, end, nums):
      p = random.randrange(start, end + 1)
      pv = nums[p]
      nums[end], nums[p] = nums[p], nums[end]
      mid = start
      for i in range(start, end):
        if nums[i] >= pv: # 左侧大
          nums[i], nums[mid] = nums[mid], nums[i]
          mid += 1
      nums[mid], nums[end] = nums[end], nums[mid]
      return mid

    ret = quickselect(0, len(nums) - 1, nums, k - 1)
    return ret

方法2:

class Solution:
    def findKthLargest(self, nums: List[int], k: int) -> int:
        q=[]
        for i in nums:
            heappush(q,i)
            if len(q)> k:
                heappop(q)
        return q[0]

470.用 Rand7() 实现 Rand10()
套路1:(randX() - 1) * Y + randY() 可以生成1~X*Y的随机数(题目rand7可以生成 1~49的随机数)
套路2:randm() = randn() % m + 1, n > m,且n%m = 0(题目的rand10可以用rand40生成)
套路3:拒绝采样(1~49的随机数丢弃40以上的数就等价于rand40)

class Solution:
    def rand10(self):
        """
        :rtype: int
        """
        while True:
            tmp = (rand7()-1)*7+rand7()
            if tmp <=40:
                return tmp%10+1

234.回文链表
本质上是判断是否对称,步骤:1.找中点2.中点后逆序3.判断是否一致
逆序记忆方法:while中间–上一行的右边等于下一行的左边
参考:https://www.youtube.com/watch?v=GTKm1PrYjwo&ab_channel=%E8%B4%BE%E8%80%83%E5%8D%9A

class Solution:
    def isPalindrome(self, head: ListNode) -> bool:
        def reverseList(root):
            pre = None
            cur = root
            while cur:
                tmp = cur.next
                cur.next = pre
                pre = cur
                cur = tmp
            return pre

        slow = fast = head
        while fast and fast.next:
            slow = slow.next
            fast = fast.next.next

        newHead = reverseList(slow)
        p1 = head
        p2 = newHead
        while p1 and p2:
            if p1.val != p2.val:
                return False
            p1 = p1.next
            p2 = p2.next
        return True

1.两数之和

class Solution(object):
  def twoSum(self, nums, target):
    """
    :type nums: List[int]
    :type target: int
    :rtype: List[int]
    """
    d = {}
    for i, num in enumerate(nums):
      if target - num in d:
        return [d[target - num], i]
      d[num] = i
    # no special case handling because it's assumed that it has only one solution

70.爬楼梯
斐波那契数列,可以分解为(n-2的结果+2)和(n-1的结果+1)

class Solution(object):
 def climbStairs(self, n):
   """
   :type n: int
   :rtype: int
   """
   if n <= 1:
     return 1
   first, second = 1, 1
   for i in range(2, n + 1):
     third = first + second
     first = second
     second = third
   return second

141.环形链表
若是链表无环,那么 fast 指针会先指向 Null。若是链表有环,fast 和 slow 迟早会在环中相遇。

class Solution(object):
 def hasCycle(self, head):
   """
   :type head: ListNode
   :rtype: bool
   """
   fast = slow = head
   while fast and fast.next:
     fast = fast.next.next
     slow = slow.next
     if slow == fast:
       return True
   return False

153.寻找旋转排序数组中的最小值
由于数组不包含重复元素,并且只要当前的区间长度不为1,pivot 就不会与 high 重合;而如果当前的区间长度为 1,这说明我们已经可以结束二分查找了。因此不会存在 num[pivot]=num[high]的情况

class Solution(object):
 def findMin(self, nums):
   """
   :type nums: List[int]
   :rtype: int
   """
   low, high = 0, len(nums) - 1
   while low < high:
       pivot = low + (high - low) // 2
       if nums[pivot] < nums[high]:
           high = pivot 
       else:
           low = pivot + 1
   return nums[low]

20.有效括号
方法1:

class Solution:
    def isValid(self, s: str) -> bool:
        stack=[]
        hashmap={'(':')','[':']','{':'}'}
        #如果个数是基数,直接false
        if len(s) % 2 == 1:
            return False
        for i in s:
            if i in hashmap:    #如果是左括号,则加入栈
                stack.append(i)
            elif stack and hashmap[stack[-1]] == i:
                stack.pop()     #如果是右括号,且栈非空,且等于栈末位的左括号对应的右括号,则在栈中删除左括号
            else:
                return False
        return len(stack) == 0      #有效的话此时栈为空

方法2:

class Solution(object):
 def isValid(self, s):
   """
   :type s: str
   :rtype: bool
   """
   stack = []
   d = ["()", "[]", "{}"]
   for i in range(0, len(s)):
     stack.append(s[i])
     if len(stack) >= 2 and stack[-2] + stack[-1] in d:
       stack.pop()
       stack.pop()
   return len(stack) == 0

300.最长递增子序列
方法1:动态规划,视频参考https://leetcode-cn.com/problems/longest-increasing-subsequence/solution/shi-pin-tu-jie-zui-chang-shang-sheng-zi-xu-lie-by-/

class Solution:
   def lengthOfLIS(self, nums: List[int]) -> int:
       if nums == []:
           return 0
       cell = [1]
       for i in range(1,len(nums)):
           cell.append(1)
           for j in range(i):
               if(nums[j] < nums[i]):
                   cell[i] = max(cell[i], cell[j]+1)
       return max(cell)

方法2:单调栈

class Solution(object):
 def lengthOfLIS(self, nums):
   """
   :type nums: List[int]
   :rtype: int
   """
   tail = []
   for num in nums:
     idx = bisect.bisect_left(tail, num)
     if idx == len(tail):
       tail.append(num)
     else:
       tail[idx] = num
   return len(tail)

补充:输出子序列

链接:https://www.nowcoder.com/questionTerminal/9cf027bf54714ad889d4f30ff0ae5481?f=discussion
来源:牛客网

class Solution:
   def LIS(self , arr ):
       # write code here        
       # 贪心 + 二分
       if len(arr) < 2:
           return arr
        
       ansVec = [arr[0]] # 记录以某一元素结尾的最长递增子序列,初始化为数组第一位元素
       maxLen = [1] # 记录下标i处最长递增子序列的长度,初始化为[1](下标0此时只有一个数字,长度为1)
        
       for num in arr[1:]:
           if num > ansVec[-1]:
               ansVec.append(num)  # 更新以num为结尾元素的最长递增子序列
               maxLen.append(len(ansVec))  # 同时更新此时最长递增子序列的长度
           else:
               # 二分查找第一个比num大的数字,替换
               # 此时以该元素为结尾的最长递增子序列的长度为其在ansVec中的下标+1
               left, right = 0, len(ansVec)-1
               while left < right:
                   mid = (left + right) // 2
                   if ansVec[mid] < num:
                       left = mid+1
                   elif ansVec[mid] == num:
                       left = mid
                       break
                   else:
                       if ansVec[mid-1] < num:
                           left = mid
                           break
                       else:
                           right = mid-1
               ansVec[left] = num
               maxLen.append(left+1)
        
       # ansVec不一定是最后结果,求解按字典序最小的结果
       # 此时我们知道最长长度为ansLen,从后向前遍历maxLen,
       # 遇到第一个maxLen[i]==ansLen的下标i处元素arr[i]即为所求,
       # 例:
       # [1,2,8,6,4] -> maxLen [1,2,3,3,3] -> ansLen=3
       # [1,2,8] -> [1,2,6] -> [1,2,4] 长度一致的答案,字典序越小越靠后
       ansLen = len(ansVec)
       for i in range(len(arr)-1, -1, -1):
           if maxLen[i] == ansLen:
               ansVec[ansLen-1] = arr[i]
               ansLen -= 1
                
       return ansVec

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

class Solution:
   def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
       n1 = len(nums1)
       n2 = len(nums2)
       if n1 > n2:
           return self.findMedianSortedArrays(nums2,nums1) # 确保分割线左右两边都有元素,如果首先是长的,可能只在长的中间有分割线就ok
       k = (n1 + n2 + 1)//2 # 不论奇偶,分割线左边元素个数满足条件
       left = 0
       right = n1
       while left < right :
           m1 = left +(right - left)//2 # 二分查找
           m2 = k - m1
           if nums1[m1] < nums2[m2-1]: # 交叉小于等于,即分割线左侧的小于分割线右侧的
               left = m1 + 1
           else:
               right = m1
       m1 = left
       m2 = k - m1 
       c1 = max(nums1[m1-1] if m1 > 0 else float("-inf"), nums2[m2-1] if m2 > 0 else float("-inf") )
       if (n1 + n2) % 2 == 1:
           return c1
       c2 = min(nums1[m1] if m1 < n1 else float("inf"), nums2[m2] if m2 <n2 else float("inf"))
       return (c1 + c2) / 2

5.最长回文子串
中心扩散

class Solution:
  def longestPalindrome(self, s: str) -> str:
      res, n = "", len(s)
      for i in range(n):
          l = r = i # 中心是奇数
          while l >= 0 and r < n and s[l] == s[r]:
              l -= 1
              r += 1
          if r - l - 1 > len(res): # 多减了,r-(l+1)
              res = s[l+1:r] # 这边同样由于多减了两遍都取不到
          l, r = i, i + 1 # 中心是偶数
          while l >= 0 and r < n and s[l] == s[r]:
              l -= 1
              r += 1
          if r - l - 1 > len(res):
              res = s[l+1:r]
      return res

补充题6.堆排序
参考:https://zhuanlan.zhihu.com/p/151720319

        def maxHepify(arr, i, end):     # 大顶堆
           j = 2*i + 1             # j为i的左子节点【建堆时下标0表示堆顶】
           while j <= end:         # 自上而下进行调整
               if j+1 <= end and arr[j+1] > arr[j]:    # i的左右子节点分别为j和j+1
                   j += 1                              # 取两者之间的较大者
               
               if arr[i] < arr[j]:             # 若i指示的元素小于其子节点中的较大者
                   arr[i], arr[j] = arr[j], arr[i]     # 交换i和j的元素,并继续往下判断
                   i = j                       # 往下走:i调整为其子节点j
                   j = 2*i + 1                 # j调整为i的左子节点
               else:                           # 否则,结束调整
                   break
       

       n = len(nums)
       
       # 建堆【大顶堆】堆初始化,从下往上
       for i in range((n-1)//2, -1, -1):   # 从第一个非叶子节点(n-1)//2开始依次往上进行建堆的调整
           maxHepify(nums, i, n-1)

       # 排序:依次将堆顶元素(当前最大值)放置到尾部,并调整堆
       for j in range(n-1, -1, -1):
           nums[0], nums[j] = nums[j], nums[0]     # 堆顶元素(当前最大值)放置到尾部j
           maxHepify(nums, 0, j-1)                 # j-1变成尾部,并从堆顶0开始调整堆,从上往下
       
       return nums

15.三数之和
排序+双指针+特殊情况考虑

class Solution(object):
 def threeSum(self, nums):
   """
   :type nums: List[int]
   :rtype: List[List[int]]
   """
   res = []
   nums.sort()
   for i in range(0, len(nums)):
     if i > 0 and nums[i] == nums[i - 1]:
       continue
     target = 0 - nums[i]
     start, end = i + 1, len(nums) - 1
     while start < end:
       if nums[start] + nums[end] > target:
         end -= 1
       elif nums[start] + nums[end] < target:
         start += 1
       else:
         res.append((nums[i], nums[start], nums[end])) # 注意两个括号
         end -= 1
         start += 1
         while start < end and nums[end] == nums[end + 1]: # 注意==
           end -= 1
         while start < end and nums[start] == nums[start - 1]:
           start += 1
   return res

384.打乱数组
洗牌算法:等概率选择每个位置应该填哪个数。
具体来说,我们先在0 ~ n-1中随机选一个坐标,将它作为第一个,和第一个交换位置;(每个数被选到的概率是1/n);剩下的n-1个数里,继续随机一个1 ~ n-1的坐标,将它作为第二个,和第二个交换位置(每个数被选到的概率为第一次没被选到且第二次被选到 ((n-1)/n) * (1/(n-1));以此类推。每个数填到每个位置是等概率的,都是1/n

class Solution:

   def __init__(self, nums: List[int]):
       self.nums = nums

   def reset(self) -> List[int]:
       return self.nums

   def shuffle(self) -> List[int]:
       self.temp = list(self.nums)
       for i in range(len(self.nums)):
           idx = random.randint(i, len(self.nums) - 1)
           self.temp[i], self.temp[idx] = self.temp[idx], self.temp[i]
       return self.temp

####### Your Solution object will be instantiated and called as such:
####### obj = Solution(nums)
####### param_1 = obj.reset()
####### param_2 = obj.shuffle()

226.翻转二叉树
递归

class Solution:
   def invertTree(self, root: TreeNode) -> TreeNode:
       if not root:
           return root
       
       left = self.invertTree(root.left)
       right = self.invertTree(root.right)
       root.left,root.right=right,left
       return root

347.前 K 个高频元素
堆排序

from collections import Counter
import heapq
class Solution:
  def topKFrequent(self, nums: List[int], k: int) -> List[int]:
      q=[]
      for num,freq in Counter(nums).items(): 
          if len(q)==k:
              heappushpop(q,(freq,num)) # 注意这里要和for的时候顺序反一下
          else:
              heappush(q,(freq,num))
      return [x[1] for x in q]

451.根据字符出现频率排序

class Solution:
   def frequencySort(self, s: str) -> str:
       Map = Counter(s)
       ans = ''
       for char, num in sorted(list(Map.items()), key = lambda x: -x[1]):
           ans += char * num
       return ans

1452.收藏清单

class Solution:
   def peopleIndexes(self, f: List[List[str]]) -> List[int]:
       ans = []
       f = [set(x) for x in f]
       for i,x in enumerate(f):
           flag = 0
           for j, y in enumerate(f):
               if i==j: continue
               if x&y==x:
                   flag = 1
                   break
           if flag==0:
               ans.append(i)
       return ans

25.K 个一组翻转链表

class Solution:
   def reverseKGroup(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
       def rev(a,b): # 指定区间反转,到b结束,注意这里是两个输入
           pre=None
           cur=a
           while cur!=b: # b节点只在这里用了一次
               tmp=cur.next
               cur.next=pre
               pre=cur
               cur=tmp
           return pre
       
       a=b=head # 初始化头结点
       for i in range(k): # 找到k节点之后的节点
           if not b:
               return head
           b=b.next
       n=rev(a,b) # 这个时候a在尾部,反转a-b区间的k个节点
       a.next=self.reverseKGroup(b,k) # 递归更新尾节点的指针
       return n

102.二叉树的层序遍历

class Solution:
    def levelOrder(self, root: TreeNode) -> List[List[int]]:

        if root == None:
            return []

        res = []
        queue = [root]

        while queue:
            res.append([node.val for node in queue])
            # 存储当前层的孩子节点列表
            childNodes = []

            for node in queue:
                # 若节点存在左孩子,入队
                if node.left:
                    childNodes.append(node.left)
                # 若节点存在右孩子,入队
                if node.right:
                    childNodes.append(node.right)
            # 更新队列为下一层的节点,继续遍历
            queue = childNodes
        return res

103.二叉树的锯齿形层序遍历
方法1:参考102针对奇偶使用逆序

class Solution:
    def zigzagLevelOrder(self, root: TreeNode) -> List[List[int]]:
        if not root:
            return []

        res = []
        queue = [root]
        f=0 # 多出

        while queue:
            if f%2==0: #
                res.append([node.val for node in queue])
            else: #
                res.append([node.val for node in queue[::-1]]) # 多出
            childNodes = []

            for node in queue:
                if node.left:
                    childNodes.append(node.left)
                if node.right:
                    childNodes.append(node.right)
            queue = childNodes
            f+=1 # 多出
        return res

方法2:双端队列

class Solution:
    def zigzagLevelOrder(self, root: TreeNode) -> List[List[int]]:
        if not root:return []
        q = collections.deque([root])
        f = True
        ans = []
        while q:
            tmp = collections.deque([]) # 用一个双端队列来存结果
            for _ in range(len(q)):
                n = q.popleft()
                if f: tmp.append(n.val) # 正向存结果
                else: tmp.appendleft(n.val) # 反向存结果
                if n.left:q.append(n.left)
                if n.right:q.append(n.right)
            f = not f # 标志位反转
            ans.append(list(tmp))
        return ans

121.买卖股票的最佳时间

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        if not prices:
            return 0
        ans=0
        pre=prices[0]
        for i in range(1,len(prices)): #注意是range(1,len())
            pre=min(pre,prices[i])
            ans=max(ans,prices[i]-pre)
        return ans

160.相交链表

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        if not headA or not headB:
            return None
        
        pa=headA
        pb=headB
        while pa != pb:
            pa = headB if not pa else pa.next
            pb = headA if not pb else pb.next
        return pa

236.二叉树的最近公共祖先
注意最近公共祖先的定义,且二叉树问题一般都可以通过递归解决

class Solution:
   def lowestCommonAncestor(self, root: TreeNode, p: TreeNode, q: TreeNode) -> TreeNode:
       if not root or root == p or root == q: return root
       left = self.lowestCommonAncestor(root.left, p, q)
       right = self.lowestCommonAncestor(root.right, p, q)
       if not left and not right: return # 1. 可以合并到 3 / 4 里
       if not left: return right # 3.
       if not right: return left # 4.
       return root # 2. if left and right

88.合并两个有序数组:逆向双指针

class Solution:
    def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
        """
        Do not return anything, modify nums1 in-place instead.
        """
        p1, p2 = m - 1, n - 1
        tail = m + n - 1
        while p1 >= 0 or p2 >= 0:
            if p1 == -1:
                nums1[tail] = nums2[p2]
                p2 -= 1
            elif p2 == -1:
                nums1[tail] = nums1[p1]
                p1 -= 1
            elif nums1[p1] > nums2[p2]:
                nums1[tail] = nums1[p1]
                p1 -= 1
            else:
                nums1[tail] = nums2[p2]
                p2 -= 1
            tail -= 1

33.搜索旋转排序数组:
可以遍历,但为了提高效率用二分法(该题条件下,肯定有一边是有序的)

class Solution(object):
    def search(self, nums, target):
        if not nums:
            return -1
        left = 0
        right = len(nums) - 1
        while left <= right:
            mid = (right + left) // 2
            if nums[mid] == target:
                return mid
            if nums[mid] >= nums[left]:
                if nums[left] <= target <= nums[mid]:
                    right = mid - 1
                else:
                    left = mid + 1
            else:
                if nums[mid] <= target <= nums[right]:
                    left = mid + 1
                else:
                    right = mid - 1
        return -1

23.合并k个升序链表

class Solution:
   def mergeKLists(self, lists: List[ListNode]) -> ListNode:
       import heapq #调用堆
       minHeap = []
       for listi in lists: 
           while listi: #由于是链表所以要while和后续的.val和.next
               heapq.heappush(minHeap, listi.val) #把listi中的数据逐个加到堆中,且由于是二叉树,仅从数来看不是严格递增的
               listi = listi.next
       dummy = ListNode(0) #构造虚节点
       p = dummy
       while minHeap: #heap是二叉树,用for i in minHeap,遍历得到的输出不全,所以要while,不断pop到没有值
           p.next = ListNode(heapq.heappop(minHeap)) #依次弹出最小堆的数据,注意要加上listnode,否则是一个整数值
           p = p.next
       return dummy.next  #return p.next为null,return p为6,所以只能是dummy

OJ在线编程常见输入输出练习场

import sys
for line in sys.stdin:
  print(sum(map(int,line.split())))
n = int(input())
for i in range(n):
   a,b = map(int, input().split())
   print(a+b)
while True:
   a, b = map(int, input().split())
   if a == 0 and b == 0:
       break
   else:
       print(a+b)
while True:
   l = list(map(int, input().split()))
   if l[0] > 0:
       print(sum(l[1:]))
   else:
       break
n = int(input())
for i in range(n):
   nums = list(map(int,input().split()))
   print(sum(nums)-nums[0])
while True:
   try:
       nums = list(map(int,input().split()))
       print(sum(nums)-nums[0])
   except:
       break
while True:
    try:
        nums = list(map(int,input().split()))
        print(sum(nums))
    except:
        break
n = int(input())
string = input().split(' ')
print(" ".join(sorted(string)))
while True:
   try:
       a = input().split()
       a.sort()
       print(' '.join(a))
   except:
       break
while True:
   try:
       a = input().split(',')
       a.sort()
       print(','.join(a))
   except:
       break
a,b=map(int,input().split())
print(a+b)
import sys
if __name__ == "__main__":
    # 读取第一行的n
    n = int(sys.stdin.readline().strip())
    ans = 0
    for i in range(n):
        # 读取每一行
        line = sys.stdin.readline().strip()
        # 把每一行的数字分隔后转化成int列表
        values = list(map(int, line.split()))
        for v in values:
            ans += v
    print(ans)

剑指Offer

09.用两个栈实现队列

class CQueue:
    def __init__(self):
        self.A, self.B = [], []

    def appendTail(self, value: int) -> None:
        self.A.append(value)

    def deleteHead(self) -> int:
        if self.B: return self.B.pop() #两个if的顺序和答案能否通过有关系
        if not self.A: return -1
        while self.A:
            self.B.append(self.A.pop())
        return self.B.pop()

30.包含min函数的栈

class MinStack:

    def __init__(self):
        """
        initialize your data structure here.
        """
        self.A,self.B=[],[]

    def push(self, x: int) -> None:
        self.A.append(x)
        if not self.B or self.B[-1]>=x:
            self.B.append(x)

    def pop(self) -> None:
        if self.A.pop()==self.B[-1]:
            self.B.pop()

    def top(self) -> int:
        return self.A[-1]

    def min(self) -> int:
        return self.B[-1]


# Your MinStack object will be instantiated and called as such:
# obj = MinStack()
# obj.push(x)
# obj.pop()
# param_3 = obj.top()
# param_4 = obj.min()

06.从尾到头打印链表

class Solution:
    def reversePrint(self, head: ListNode) -> List[int]:
        stack = []
        while head:
            stack.append(head.val)
            head = head.next
        return stack[::-1]

24.反转链表


35.复杂链表的复制

"""
# Definition for a Node.
class Node:
    def __init__(self, x: int, next: 'Node' = None, random: 'Node' = None):
        self.val = int(x)
        self.next = next
        self.random = random
"""
class Solution:
    def copyRandomList(self, head: 'Node') -> 'Node':
        if not head: return
        dic = {}
        # 3. 复制各节点,并建立 “原节点 -> 新节点” 的 Map 映射
        cur = head
        while cur:
            dic[cur] = Node(cur.val)
            cur = cur.next
        cur = head
        # 4. 构建新节点的 next 和 random 指向
        while cur:
            dic[cur].next = dic.get(cur.next) # .get是根据键返回值
            dic[cur].random = dic.get(cur.random)
            cur = cur.next
        # 5. 返回新链表的头节点
        return dic[head]

05.替换空格

class Solution:
    def replaceSpace(self, s: str) -> str:
        res = []
        for c in s:
            if c == ' ': res.append("%20")
            else: res.append(c)
        return "".join(res)

58 - II.左旋转字符串

class Solution:
    def reverseLeftWords(self, s: str, n: int) -> str:
        return s[n:] + s[:n]

03.数组中重复的数字
set和dict类似,也是一组key的集合,但不存储value。由于key不能重复,所以,在set中,没有重复的key

class Solution:
    def findRepeatNumber(self, nums: [int]) -> int:
        dic = set()
        for num in nums:
            if num in dic: return num
            dic.add(num)
        return -1

53 - I.在排序数组中查找数字 I
排序数组中的搜索问题,首先想到 二分法 解决,// 为向下取整除法

class Solution:
    def search(self, nums: [int], target: int) -> int:
        def helper(tar):
            i, j = 0, len(nums) - 1
            while i <= j:
                m = (i + j) // 2
                if nums[m] <= tar: i = m + 1
                else: j = m - 1
            return i # 这里j最后会-1,所以返回i
        return helper(target) - helper(target - 1)

53 - II.0~n-1中缺失的数字

class Solution:
    def missingNumber(self, nums: List[int]) -> int:
        i, j = 0, len(nums) - 1
        while i <= j:
            m = (i + j) // 2
            if nums[m] == m: i = m + 1
            else: j = m - 1
        return i

04.二维数组中的查找

class Solution:
    def findNumberIn2DArray(self, matrix: List[List[int]], target: int) -> bool:
        i, j = len(matrix) - 1, 0
        while i >= 0 and j <= len(matrix[0])-1:
            if matrix[i][j] > target: i -= 1
            elif matrix[i][j] < target: j += 1
            else: return True
        return False

50.第一个只出现一次的字符

class Solution:
    def firstUniqChar(self, s: str) -> str:
        dic = {}
        for c in s:
            dic[c] = not c in dic
        for c in s:
            if dic[c]: return c
        return ' '

11.旋转数组的最小数字

class Solution:
    def minArray(self, numbers: [int]) -> int:
        i, j = 0, len(numbers) - 1
        while i <= j:
            m = (i + j) // 2
            if numbers[m] > numbers[j]: i = m + 1
            elif numbers[m] < numbers[j]: j = m #注意这里没有-1
            else: j -= 1 #这种情况-1
        return numbers[i]

32 - I.从上到下打印二叉树
栈先入后出,队列先入先出

class Solution:
    def levelOrder(self, root: TreeNode) -> List[int]:
        if not root: return []
        res, queue = [], collections.deque()
        queue.append(root) #是一个整体
        while queue:
            node = queue.popleft()
            res.append(node.val)
            if node.left: queue.append(node.left)
            if node.right: queue.append(node.right)
        return res

32 - II.从上到下打印二叉树 II

class Solution:
    def levelOrder(self, root: TreeNode) -> List[List[int]]:
        if not root: return []
        res, queue = [], collections.deque()
        queue.append(root)
        while queue:
            tmp = []
            for _ in range(len(queue)):
                node = queue.popleft()
                tmp.append(node.val)
                if node.left: queue.append(node.left)
                if node.right: queue.append(node.right)
            res.append(tmp)
        return res

32 - III.从上到下打印二叉树 III

class Solution:
    def levelOrder(self, root: TreeNode) -> List[List[int]]:
        if not root: return []
        res, queue = [], collections.deque()
        queue.append(root)
        while queue:
            tmp = []
            for _ in range(len(queue)):
                node = queue.popleft()
                tmp.append(node.val)
                if node.left: queue.append(node.left)
                if node.right: queue.append(node.right)
            res.append(tmp[::-1] if len(res) % 2 else tmp)
        return res

26.树的子结构
先找节点,然后再看是否一致

class Solution:
    def isSubStructure(self, A: TreeNode, B: TreeNode) -> bool:
        def recur(A, B):
            if not B: return True
            if not A or A.val != B.val: return False
            return recur(A.left, B.left) and recur(A.right, B.right)

        return bool(A and B) and (recur(A, B) or self.isSubStructure(A.left, B) or self.isSubStructure(A.right, B))

27.二叉树的镜像


class Solution:
    def mirrorTree(self, root: TreeNode) -> TreeNode:
        if not root: return
        root.left, root.right = self.mirrorTree(root.right), self.mirrorTree(root.left)
        return root

28.对称的二叉树

class Solution:
    def isSymmetric(self, root: TreeNode) -> bool:
        def recur(L, R):
            if not L and not R: return True
            if not L or not R or L.val != R.val: return False
            return recur(L.left, R.right) and recur(L.right, R.left)

        return recur(root.left, root.right) if root else True

10- I.斐波那契数列

class Solution:
    def fib(self, n: int) -> int:
        a, b = 0, 1
        for _ in range(n):
            a, b = b, a + b
        return a % 1000000007

10- II.青蛙跳台阶问题

class Solution:
    def numWays(self, n: int) -> int:
        a, b = 1, 1
        for _ in range(n):
            a, b = b, a + b
        return a % 1000000007

63.股票的最大利润

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        cost, profit = float("+inf"), 0
        for price in prices:
            cost = min(cost, price)
            profit = max(profit, price - cost)
        return profit

60.n个骰子的点数

class Solution:
    def dicesProbability(self, n: int) -> List[float]:
        dp = [1 / 6] * 6
        for i in range(2, n + 1):
            tmp = [0] * (5 * i + 1)
            for j in range(len(dp)):
                for k in range(6):
                    tmp[j + k] += dp[j] / 6
            dp = tmp
        return dp

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值