刷LeetCode记录(持续更新)

2022年9月2日

记录一下学习历程,方便以后回顾,同时也是想起到监督作用。今天先刷刷简单题吧,太菜了 。

1. 两数之和

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
题目链接:https://leetcode.cn/problems/two-sum
在这里插入图片描述

## 哈希map
recode = dict()   # 建立map key存列表的数据,value存数据在列表中的index
for idx,val in enumerate(nums):  ## 遍历数组
    if target-val not in recode:  ##判断目标值与当前值的差值是否存在map中
        recode[val] = idx   
    else:
        return [recode[target-val],idx]  

9.回文数

给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。
回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
例如,121 是回文,而 123 不是。
题目链接:https://leetcode.cn/problems/palindrome-number
在这里插入图片描述

# 简单粗暴,把int直接变成str,直接比较 
return str(x) == str(x)[::-1]

13.罗马数字转整数

罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。
在这里插入图片描述
题目链接:https://leetcode.cn/problems/roman-to-integer
在这里插入图片描述

text = {'I':1,'V':5,'X':10,'L':50,'C':100,'D':500,'M':1000}
ans = 0
#从左到右来,如果当前字符代表的值不小于其右边,就加上该值;否则就减去该值。
for i in range(len(s)):
    if i<len(s)-1 and text[s[i]]<text[s[i+1]]:  
        ans -= text[s[i]]
    else:
        ans += text[s[i]]
return ans

14.最长公共前缀

编写一个函数来查找字符串数组中的最长公共前缀。如果不存在公共前缀,返回空字符串 “”。
题目链接:https://leetcode.cn/problems/longest-common-prefix/
在这里插入图片描述
两种方法:

方法一
####  使用zip 函数将和set函数完成
"
	1zip函数将对象中对应的元素打包成一个元组,加*会打包成一个列表
	例如:
	a = [1,2]
	b = [4,5]
	c = zip(a,b)
	>> c = [(1,4),(2,5)]
	
	2、而set函数则是将列表中重复的元素去掉
	例如:
	a = [1,2,1,3,2]
	b = set(a)
	>> b = [1,2,3]
"

ans = ""
for tup in zip(*strs):
    if len(set(tup)) == 1:
        ans += tup[0]
    else:
         break
return ans
方法2
#根据 ASCII 得到最大值和最小值的字符串
s1 = min(strs)   
s2 = max(strs)
for idx,val in enumerate(s1):#遍历ASCII 最小值字符串
    if val != s2[idx]: # 判断与最大的是否相同
        return s1[:idx] 
return s1

20.有效的括号

给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
每个右括号都有一个对应的相同类型的左括号。
题目链接:https://leetcode.cn/problems/valid-parentheses
在这里插入图片描述

#堆栈的方法
stack = [] 
for item in s: #  遍历字符串
    if item == '(':
        stack.append(')')  # 堆上括号的另一半 后续一样
    elif item == '[':
        stack.append(']')
    elif item == '{':
        stack.append('}')
   #如果栈是空的,或者说栈的最后一个与当前字符不一样,那就返回False
    elif not stack or stack[-1] != item: 
        return False
    else:
        stack.pop()     ## 弹栈,把最后存入的删除掉
return True if not stack else False   ## 如果栈没弹干净说明存在不成对的括号。

26.删除有序数组中的重复项

给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。
由于在某些语言中不能改变数组的长度,所以必须将结果放在数组nums的第一部分。更规范地说,如果在删除重复项之后有 k 个元素,那么 nums 的前 k 个元素应该保存最终结果。
将最终结果插入 nums 的前 k 个位置后返回 k 。
不要使用额外的空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

题目链接:https://leetcode.cn/problems/remove-duplicates-from-sorted-array
在这里插入图片描述

for i in range(len(nums)-1,0,-1):  ## 从后往前遍历
   if nums[i] == nums[i-1]:
       del nums[i]

2022年9月3日

27.移除元素

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
题目链接:https://leetcode.cn/problems/remove-element
在这里插入图片描述

##  大力出奇迹方法
for i in range(len(nums)-1,-1,-1):
if nums[i] == val:
    nums.pop(i)
## 快慢双指针
slowIndex = fastIndex = 0
while fastIndex<len(nums):
	if nums[fastIndex] != val:
		nums[slowIndex] = nums[fastIndex]
		slowIndex += 1
	fastIndex +=1
return slowIndex

35. 搜索插入位置

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 O(log n) 的算法。
题目链接:https://leetcode.cn/problems/search-insert-position
在这里插入图片描述

 # 快慢双指针   
 slow = 0 
 fast = 0
 while fast < len(nums):
     if nums[fast] < target:
         slow += 1
     fast += 1
 return slow
## 暴力
for i in range(len(nums)):
	if nums[i] >= target:
	    return i
return i+1
## 二分法
left = 0
right = len(nums)-1
while left <= right:
    mid = int((left + right) / 2)
    if nums[mid] > target:
        right -= 1
    elif nums[mid] < target:
        left += 1
    else:
        return mid
return right+1

58. 最后一个单词的长度

给你一个字符串 s,由若干单词组成,单词前后用一些空格字符隔开。返回字符串中 最后一个 单词的长度。
单词 是指仅由字母组成、不包含任何空格字符的最大子字符串。
题目链接:https://leetcode.cn/problems/length-of-last-word
在这里插入图片描述

## 直接把字符串切片成列表,取最后一个求取长度就行
return len(s.split()[-1] )

66. 加一

给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。
最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。
你可以假设除了整数 0 之外,这个整数不会以零开头。
题目链接:https://leetcode.cn/problems/plus-one
在这里插入图片描述

## 笨方法
class Solution:
    def plusOne(self, digits: List[int]) -> List[int]:
        i = 0
        ans = 0
        for digit in reversed(digits):
            ans += digit*(10**i)
            i +=1
        ans += 1
        res = []
        j = 1
        while ans > 0:
            mid_num = 10**(j)
            res.append(ans%10)
            ans =ans//10
        return res[::-1]

67.二进制求和

给你两个二进制字符串,返回它们的和(用二进制表示)。
输入为 非空 字符串且只包含数字 1 和 0。
题目链接:https://leetcode.cn/problems/add-binary/
在这里插入图片描述
这提其实完全可以用python自带的内置函数来做,也就一行代码。

return bin(int(a,2)+int(b,2))[2:]

不过既然是来学习的,那就最好自己写一写。

## 永远b是最短的
if len(a) < len(b):
   a ,b = b,a
## 求取长度相差多少
diff = len(a) - len(b)
# 用0把b的长度填充和a一样长
b = "0"*diff+b
mid = 0
ans = ''
# 逆序相加
for i in range(len(a)-1,-1,-1):  
	# 取出对应的元素相加 
    res = int(a[i])+int(b[i])+mid
    # 如果为2 那就进1,同时0添加到ans中
    if res == 2:
        mid = 1
        ans = '0' + ans
        # 如果是最后一位了,就要长度多加一个1
        if i == 0:
            ans = '1' + ans
     # 如果为3 那就进1 同时1添加到ans中
    elif res == 3:
        mid = 1
        ans = '1' + ans
        if i == 0:
            ans = '1' + ans
    else:
        mid = 0
        ans = str(res) + ans
return ans

69. x 的平方根

给你一个非负整数 x ,计算并返回 x 的 算术平方根 。
由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。
题目链接:https://leetcode.cn/problems/sqrtx/
在这里插入图片描述

#最简单的方法,就是使用内置函数sqrt()
return int(sqrt(x))
# 另外可以用牛顿法
if x <= 1:
	return x
r = x
while r > x/r:
	r = (r + x/r)//2
return int(r)

70.爬楼梯

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
题目链接:https://leetcode.cn/problems/climbing-stairs/
在这里插入图片描述
这是一题简单的动态规划题目,和斐波那契数 异曲同工,主要是把公式推到出来。
由题我们可以知道
n = 1 ---->>> 1
n = 2 ----->>>2
n = 3 ---->>> 3
n = 4 ---->>> 5
由此可推出 F(n)= F(n-2)+F(n-1)

class Solution:
    def climbStairs(self, n: int) -> int:
        ans = [1,2]
        if n <=2:
            return ans[n-1]
        for i in range(2,n):
            ans.append(ans[i-2]+ans[i-1])
        return ans[-1]

509.斐波那契数

在这里插入图片描述
题目链接:https://leetcode.cn/problems/fibonacci-number/

class Solution:
    def fib(self, n: int) -> int:
        ans = [0,1]
        if n<2:
            return ans[n]
        for i in range(2,n+1):
            ans.append(ans[i-2]+ans[i-1])
        return ans[-1]

2022年 9月4日

88.合并两个有序数组

给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。
请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。
注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。
题目链接:https://leetcode.cn/problems/merge-sorted-array
在这里插入图片描述
这题其实nums1的长度是m+n的,因此不需要改变nums1的长度,直接在上面处理就行

'
python的简单粗暴的方法,因为默认nums1只有前m个是非0的数字,因此直接切片后续的数字变为nums2中的元素
'
nums1[m:] = nums2
nums1.sort()
双指针,一个指向nums1,另一个指向nums2,我这里还考虑了0可能在前面的情况,如果不考虑的话,会更简单。
 i = len(nums1) - 1
 j = n - 1
  while True:
      if nums1[i] == 0:
          nums1[i] = nums2[j]
          i -= 1
          j -= 1
      else:
          i -= 1
      if i<0 or j <0:
          break
  nums1.sort()
## 这个不考虑前面有0的情况,直接按题目的意思来。
i = len(nums1) - 1
j = n - 1
while j >-1:
    nums1[i] = nums2[j]
    i -= 1
    j -= 1
nums1.sort()

118. 杨辉三角

在这里插入图片描述
题目链接:https://leetcode.cn/problems/pascals-triangle/

class Solution:
    def generate(self, numRows: int) -> List[List[int]]:
        results = []
        for i in range(numRows):
            result = [1]
            for j in range(i):
                if j < i-1:
                    result.append(results[i-1][j]+results[i-1][j+1])
                else:
                    result.append(1)
            results.append(result)
        return results

119. 杨辉三角II

在这里插入图片描述
题目链接:https://leetcode.cn/problems/pascals-triangle-ii/
这题和杨辉三角其实是一样的,只不过返回的数据有所差别仅此而已。

class Solution:
    def getRow(self, rowIndex: int) -> List[int]:
        results = []
        for i in range(rowIndex+1):
            result = [1]
            for j in range(i):
                if j < i - 1:
                    result.append(results[i-1][j]+results[i-1][j+1])
                else:
                    result.append(1)
            results.append(result)
        return results[-1]

121.买卖股票的最佳时机

给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。
你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。
返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。
题目链接:https://leetcode.cn/problems/best-time-to-buy-and-sell-stock

贪心算法
class Solution:
    def maxProfit(self, prices: List[int]) -> int:
    # 如果给的价格只有一个,那么就直接返回0
        if len(prices) <= 1:
            return 0 
      # 把第一天的价格默认为最低价
        min_price = prices[0]
       # 最大利润默认为 0 
        max_profit = 0
        # 遍历价格
        for price in prices:
        #挑选出最低的进货价格
            min_price = min(min_price,price)
        ## 计算当前利润
            cur_profit = price - min_price
         # 比较当前利润和最大利润取两者中最大值
            max_profit = max(max_profit,cur_profit)
        return max_profit
动态规划
class Solution:
    def maxProfit(self, prices: List[int]) -> int:
		days = len(prices)
		dp = [[0]*days,[0]*days]
		##  dp 初始化
		dp[0][0] = - prices[0]
		dp[1][0] = 0
		for i in range(1,days):
		    dp[0][i] = max(dp[0][i-1],-prices[i])
		    dp[1][i] = max(dp[1][i-1],dp[0][i-1]+prices[i])
		return dp[1][-1]
592. 分数加减运算

给定一个表示分数加减运算的字符串 expression ,你需要返回一个字符串形式的计算结果。
这个结果应该是不可约分的分数,即最简分数。 如果最终结果是一个整数,例如 2,你需要将它转换成分数形式,其分母为 1。所以在上述例子中, 2 应该被转换为 2/1。
题目链接:https://leetcode.cn/problems/fraction-addition-and-subtraction

### 暴力解法
import numpy
from math import gcd
class Solution:
    def fractionAddition(self, expression: str) -> str:
        stack = []
        ## 把一个个分数切割出来成列表,如果是减法直接分子为负值。
        # 如 "-1/2+1/2+1/3"  --->>> [[-1,2],[1,2],[1,3]]
        for i in expression.replace('-', '+-').split('+'):
            if i:
                stack.append(list(map(int ,i.split('/'))))
        ## 用zip函数,把分子和分母分开
        ## [[-1,1,1],[2,2,3]]
        stack = list(zip(*stack)) 
        molecule = 0
        # 取出所有分子
        molecules = list(stack[0])
        # 取出所有分母
        denominators = list(stack[1])
        # 所有分母相乘 即 y1*y2*y3
        denominator = int(numpy.prod(denominators))
        for i in range(len(molecules)):
            denominator_ = denominators[:]
            denominator_.pop(i)
            #分子与分母的相乘 如:x1*y2*y3
            molecule += molecules[i]*numpy.prod(denominator_)
        molecule = int(molecule)
        denominator = int(denominator)
        if molecule == 0:
            return '0/1'
        if molecule < 0:
            molecule *= -1
            g = gcd(molecule,denominator)
            return '-{}/{}'.format(int(molecule/g),int(denominator/g))
        else:
            g = gcd(molecule, denominator)
            return '{}/{}'.format(int(molecule / g), int(denominator / g))

2022年9月14日。

前段时间学习动态规划了,而且忙着找工作,还要复习一下知识点。
136.只出现一次的数字

在这里插入图片描述
题目链接:https://leetcode.cn/problems/single-number/

异或运算

在这里插入图片描述

class Solution:
    def singleNumber(self, nums: List[int]) -> int:
        # 异或运算
        ans = 0
        for num in nums:
            ans ^= num
        return ans
暴力解法

直接计算出现的次数,若重复出现则删掉。

class Solution:
    def singleNumber(self, nums: List[int]) -> int:
        nums_map = dict()
        for num in nums:
            if num not in nums_map:
                nums_map[num] = 1
            else:
                del nums_map[num]
        return list(nums_map.keys())[0]

用列表直接存 时间居然比用字典存的要多十多倍?这是为什么呢??

class Solution:
    def singleNumber(self, nums: List[int]) -> int:
        nums_map = []
        for num in nums:
            if num not in nums_map:
                nums_map.append(num)
            else:
                nums_map.remove(num)
        return nums_map[0]
350. 两个数组的交集 II

在这里插入图片描述
**分析:**其实这题的思路就是 计算nums1中各个数母的出现次数,当nums2中出现时就减去一个并保留下来.

class Solution:
    def intersect(self, nums1: List[int], nums2: List[int]) -> List[int]:
        # map
        nums1_map = dict()
        for nums in nums1:
            if nums not in nums1_map:
                nums1_map[nums] = 1
            else:
                nums1_map[nums] += 1
        ans = []
        for nums in nums2:
            if nums in nums1_map and nums1_map[nums] != 0:
                ans.append(nums)
                nums1_map[nums] -= 1
        return ans
## 双指针
class Solution:
    def intersect(self, nums1: List[int], nums2: List[int]) -> List[int]:
        nums1 = sorted(nums1)
        nums2 = sorted(nums2)
        if len(nums1) > len(nums2):
            # 始终认为 nums1为最短的数组
            nums1,nums2 = nums2,nums1
        nums1_p = 0
        nums2_p = 0
        ans = []
        while nums2_p < len(nums2) and nums1_p <len(nums1):
            if nums1[nums1_p] == nums2[nums2_p]:
                ans.append(nums1[nums1_p])
                nums1_p += 1
                nums2_p += 1
            # 排序之后,谁小谁移动
            elif nums1[nums1_p] < nums2[nums2_p]:
                nums1_p += 1
            else:
                nums2_p += 1
        return ans
383.赎金信

在这里插入图片描述
题目链接:https://leetcode.cn/problems/ransom-note/
分析:
其实这题的思路就是 计算magazine中各个字母的出现次数,当ransomNote中出现时就减去一个,若ransomNote中出现,但magazine中没有就返回False.

class Solution:
    def canConstruct(self, ransomNote: str, magazine: str) -> bool:
        dp = [0]*26

        for x in magazine:
            dp[ord(x)-ord('a')] += 1

        for x in ransomNote:
            if dp[ord(x)-ord('a')] == 0:
                return False
            else:
                dp[ord(x)-ord('a')] -= 1
        return True
class Solution:
    def canConstruct(self, ransomNote: str, magazine: str) -> bool:
        magazineCout = dict()
        ransomNoteCout = dict()
        if len(ransomNote)>len(magazine):
            return False
        for s in magazine:
            if s not in magazineCout:
                magazineCout[s] = 1
            else:
                magazineCout[s] +=1
        for s in ransomNote:
            if s not in magazineCout:
                return False
            if s not in ransomNoteCout:
                ransomNoteCout[s] = 1
            else:
                ransomNoteCout[s] +=1
                if ransomNoteCout[s] > magazineCout[s]:
                    return False
        return True
# 上面的那个稍微改动一下
class Solution:
    def canConstruct(self, ransomNote: str, magazine: str) -> bool:		
		ransom = dict()
        magazi = dict()
        if len(ransomNote) > len(magazine):
            return False
        for x in magazine:
            if x not in magazi:
                magazi[x] = 1
            else:
                magazi[x] += 1
        for x in ransomNote:
            if x not in magazi:
                return False
            magazi[x] -= 1
            if magazi[x]<0:
                return False 
        return True
888.公平的糖果交换

在这里插入图片描述
题目链接:https://leetcode.cn/problems/fair-candy-swap/
分析:
因为最终是要两个列表得总和相等,因此我们记爱丽丝和鲍勃当前的总和为alice 和bob,然后我们要从爱丽丝和鲍勃当前中取出一个分别交换给对方,取出的分别记为x , y 。
这样我们就能得到等式 Alice - x + y = bob - y + x ,所以x = (alice-bob)//2+y

class Solution:
    def fairCandySwap(self, aliceSizes: List[int], bobSizes: List[int]) -> List[int]:
        alice = sum(aliceSizes)
        bob   = sum(bobSizes)
        mean  = (alice-bob)//2
        for y in bobSizes:
            x = y + mean
            if x in aliceSizes:
                return [x,y]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值