leetcode笔记 | 第一周

01 字符串相加

class Solution(object):
    def addStrings(self, num1, num2):
        """
        :type num1: str
        :type num2: str
        :rtype: str
        """
        # 方法1:可以使用int的话直接str->int相加再str
        return str(int(num1)+int(num2))

		# 方法2:不可以使用int则使用ascii减去‘0’得到数字,方法是chr(cur+ord('0'))
        res = ''
        carry = 0
        i = len(num1) - 1
        j = len(num2) - 1
        while i>=0 or j>=0:
            n1 = num1[i] if i>=0 else '0'
            n2 = num2[j] if j>=0 else '0'
            temp = ord(n1) + ord(n2) - 2*ord('0') + carry
            cur = temp % 10
            carry = temp // 10
            res = chr(cur+ord('0')) + res
            i -= 1
            j -= 1
        return '1'+res if carry!=0 else res
  • 时间复杂度 O ( m a x ( M , N ) ) O(max(M,N)) O(max(M,N)):其中 M,N 为两数字长度,按位遍历一遍数字(以较长的数字为准)
  • 空间复杂度 O ( 1 ) O(1) O(1):指针与变量使用常数大小空间。

03 数组中重复的数字

长度n的数组nums元素范围0~n-1,找到任意一个重复的数字。

class Solution(object):
	def findRepeatNumber(self, nums):
	"""
	:type nums: List[int]
	:rtype: int
	"""
	# 方法1:哈希表。set()不重复数组 添加元素使用.add 
	repeat = -1
	tmp = set()
	for i in range(len(nums)):
		tmp.add(nums[i])
		if len(tmp)<i+1:
			repeat = nums[i]
			break # break 跳出循环
	return repeat
	
	# PS:遇到另外一种写法非常简洁
	dic = set()
	for num in nums:
		if num in dic: return num
		dic.add(num)
	return -1

	# 方法2:排序法。sort()排序后前后相邻两个元素相同代表重复
	nums.sort()
	for i in range(len(nums)-1):
		if nums[i] == nums[i+1]:
			return nums[i]
	
	# 方法3:原地置换。有个细节就是数组n,元素范围到n-1,所以可以把数字放到其索引的位置,如果原索引位置和它相同说明出现了重复。
	i = 0
	while i < len(nums):
		if nums[i] == i:
			i += 1
			continue
		if nums[nums[i]] == nums[i]:
			return nums[i]
		nums[nums[i]], nums[i] == nums[i], nums[nums[i]] # python互换很直接
	return -1

遍历数组的时间复杂度是 O ( N ) O(N) O(N),因为跟数组的长度有关。但是交换操作的时间复杂度是 O ( 1 ) O(1) O(1),HashSet添加与查找元素也是 O ( 1 ) O(1) O(1)。 HashSet占用的空间复杂度是 O ( N ) O(N) O(N),因为不是一次性开辟了一个新的常数大小的空间,而是随着时间往里放。

04 二维数组元素查找

在从左到右和从上到下都是递增的二维数组中查找某个整数是否存在

class Solution(object):
    def findNumberIn2DArray(self, matrix, target):
        """
        :type matrix: List[List[int]]
        :type target: int
        :rtype: bool
        """

        # 法1:暴力查找,不考虑排好序问题,时间超过10%,内存超过10%
        flag = False
        for i in range(len(matrix)):
            for j in range(len(matrix[0])):
                if target == matrix[i][j]:
                    flag = True
                    break
        return flag

        # 别人的二维数组元素引用非常简洁,而且return代替了break
        for row in matrix:
            for column in row:
                if column==target:
                    return True
        return False


        # 法2:线性查找,考虑排序,从右上角开始,时间超过97%,内存超过97%
        if len(matrix)==0 or len(matrix[0])==0:
            return False # 针对[]和[[]]这种特殊情况,直接结束
        i = 0
        j = len(matrix[0]) -1
        while i < len(matrix) and j > -1:
            cur = matrix[i][j]
            if cur == target:
                return True
            elif cur < target:
                i += 1
            else:
                j -= 1
        return False


暴力方法是遍历所有元素,所以时间复杂度是 O ( M N ) O(MN) O(MN),但是排序的方法最多一整行和一整列,因此时间复杂度是 O ( M + N ) O(M+N) O(M+N)

05 替换空格

请实现一个函数,把字符串 s 中的每个空格替换成"%20"。
考虑:发现一个变成三个,提前设定一个三倍长的空的往里面填,python添加元素使用+即可
PS:python中可以直接替换函数

class Solution(object):
    def replaceSpace(self, s):
        """
        :type s: str
        :rtype: str
        """
        # 时间击败57% 内存击败91%
        lst = s.split(' ')
        return '%20'.join(lst)

        # 时间击败80%,内存击败30%
        return s.replace(' ','%20')

        # 时间击败80%,内存击败80%
        ss = ''
        for i in range(len(s)):
            if s[i] == ' ':
                ss = ss + '%20'
            else:
                ss = ss + s[i]
        return ss

06 倒序打印链表

链表只能从头到尾访问节点,而题目要求倒序打印,则需要使用栈辅助,将节点从前向后输入栈,再弹出到列表中。

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

class Solution(object):
    def reversePrint(self, head):
        """
        :type head: ListNode
        :rtype: List[int]
        """
        # 时间超过11% 内存超过11% 
        # head.val回溯当前节点值,head.next递归
        return self.reversePrint(head.next) + [head.val] if head else []

        # 时间超过70% 内存超过40%
        # 栈可以后入先出,解决链表只能从前往后
        stack = []
        while head:
            stack.append(head.val)
            head = head.next
        return stack[::-1]

head.val 当前节点 val.next 往后一个节点 循环时考虑head是否为[]代表是否到最右
列表的添加使用append() 列表的倒序使用[::-1]

832 翻转图像

python可以直接交换 a,b = b,a
A[~i]与A[i]是对称的哦,翻转的话直接^1
xrange 比 range 省空间 不过目前是差不多的

class Solution(object):
    def flipAndInvertImage(self, A):
        """
        :type A: List[List[int]]
        :rtype: List[List[int]]
        """
        for row in A:
            for i in xrange((len(row)+1)/2):
                row[i], row[~i] = row[~i]^1, row[i]^1
        return A

面试题 17.10 主要元素

超过50%的元素为主要元素。给定数组,找主要元素,没有返回-1。要求时间复杂度O(N),空间复杂度O(1)。

class Solution:
  def majorityElement(self, nums:List[int]) -> int:
    nums = sorted(nums)
    element = nums[len(nums) // 2]
    count = 0
    for ele in nums:
      if ele == element:
        count += 1
    return element if count > len(nums)/2 else -1

时间复杂度O(nlogn),空间复杂度O(n)。

class Solution:
  def majorElement(self, nums:List[int]) -> int:
    ele_dict = {}
    for ele in nums:
      if ele in ele_dict.keys():
        ele_dict[ele] += 1
      else:
        ele_dict[ele] = 1
    for key in ele_dict.keys():
      if ele_dict[keys] > len(nums)/2:
        return keys
    return -1

832 翻转图像

python可以直接交换 a,b = b,a
A[~i]与A[i]是对称的哦,翻转的话直接^1
xrange 比 range 省空间 不过目前是差不多的

class Solution(object):
   def flipAndInvertImage(self, A):
       """
       :type A: List[List[int]]
       :rtype: List[List[int]]
       """
       for row in A:
           for i in xrange((len(row)+1)/2):
               row[i], row[~i] = row[~i]^1, row[i]^1
       return A

1233 删除子文件夹

比较字符串是否在前者基础上增加可以:先排序 然后b.startswith(‘a/’)判断

class Solution(object):
    def removeSubfolders(self, folder):
        """
        :type folder: List[str]
        :rtype: List[str]
        """
        new = ['0']
        for f in sorted(folder):
            if not f.startswith(new[-1]+'/'):
                new.append(f)
        return new[1:]

969 煎饼排序

就是输入:[3,2,4,1] 输出:[4,2,4,3],输出不一定是最短序列

技巧就是找到最大的放到第一个然后丢到最后去

注意序列会变化,所以也要对arr进行改变(debug点)

列表的倒序可以使用a[::-1]表示

class Solution(object):
    def pancakeSort(self, arr):
        """
        :type arr: List[int]
        :rtype: List[int]
        """
        ans = []
        N = len(arr)
        for i in range(len(arr)):
            for j in range(N):
                if arr[j] == N:
                    ans.append(j+1)
                    arr = arr[:j+1][::-1]+arr[j+1:]
                    ans.append(N)
                    arr = arr[:N][::-1]+arr[N:]
                    N -= 1
        return ans

64 最小路径和

之前算法课听过

class Solution(object):
    def minPathSum(self, grid):
        """
        :type grid: List[List[int]]
        :rtype: int
        """
        rows, columns = len(grid), len(grid[0])
        dp = [[0] * columns for _ in range(rows)]
        dp[0][0]=grid[0][0]
        for i in range(1, rows):
            dp[i][0] = dp[i-1][0] + grid[i][0]
        for j in range(1, columns):
            dp[0][j] = dp[0][j-1] + grid[0][j]
        for i in range(1,rows):
            for j in range(1, columns):
                dp[i][j] = min(dp[i-1][j],dp[i][j-1])+grid[i][j]
        return dp[rows-1][columns-1]

78 子集

输入[1, 2, 3]输出子集,就是输出一个[[],[1],[2],[3],[1,2],[1,3],[2,3],[1,2,3]]列表,元素也是列表,所以创建新空间是[[]]。
这个列表元素添加的时候,直接用+就可以了。
+和append的区别是,对原来的序列操作是一样的,但是append是对原来序列操作,而+是产生了新序列。
在这里插入图片描述

class Solution(object):
    def subsets(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        n = len(nums)
        res = [[]]
        for num in nums:
            res += [current + [num] for current in res]
        return res

42 接雨水

在这里插入图片描述
其实就是,找到左右两边最高的,中间低就可以接到水。
要注意分别从两边查询,是双指针方法。

class Solution(object):
    def trap(self, height):
        """
        :type height: List[int]
        :rtype: int
        """
        sum = 0
        left = 0
        right = len(height) - 1
        left_max = right_max =0
        while left<=right:
            if left_max < right_max:
                sum += max(0, left_max - height[left])
                left_max = max(left_max, height[left])
                left += 1
            else:
                sum += max(0, right_max - height[right])
                right_max = max(right_max, height[right])
                right -= 1
        return sum
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值