leetcode刷题记录

leetcode高频题列表

字符串

面试题 01.06. 字符串压缩

链接

字符串压缩。利用字符重复出现的次数,编写一种方法,实现基本的字符串压缩功能。比如,字符串aabcccccaaa会变为a2b1c5a3。若“压缩”后的字符串没有变短,则返回原先的字符串。你可以假设字符串中只包含大小写英文字母(a至z)。

示例1:
输入:“aabcccccaaa”
输出:“a2b1c5a3”

示例2:
输入:“abbccd”
输出:“abbccd”
解释:“abbccd"压缩后为"a1b2c2d1”,比原字符串长度更长。

提示:
字符串长度在[0, 50000]范围内。

class Solution(object):
    def compressString(self, S):
        """
        :type S: str
        :rtype: str
        """
        S += '#'
        cnt = 0
        res = ''
        for i in range(len(S)-1):
            cnt += 1
            
            if S[i] != S[i+1]:
                res = res + S[i] + str(cnt)
                cnt = 0
                
        S = S.replace('#','')
        if len(res) < len(S):
            return res
        else:
            return S
        
if __name__ == "__main__":
    
    s = input()
    
    test = Solution()
    print(test.compressString(s))

最长回文串

链接

思路

中心扩展法

for循环一遍,判断左右是否相等,还有左右指针的边界
注意:要将原始字符串改成左右都添加#字符,让长度为奇数就可以。

class Solution(object):
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        if not s:
            return ''
        
        ss = ''
        for i in s[:len(s)]:
            ss += '#' + i
        
        ss += '#'
        s = ss
        res = ''
        
        for i in range(len(s)):
            
            cur = s[i]
            start = i-1
            end = i + 1
            while(start >= 0 and end <= len(s)-1 and s[start] == s[end]):
                cur = s[start] + cur + s[end]
                start -= 1
                end += 1
                
            if len(cur) > len(res):
                res = cur
        res = res.replace('#','')     
        return res

数组

945.使数组唯一的最小增量

134.加油站

我的思路

  1. gas 和 cost做差得到新的数组gas2,if sum(gas2) < 0 return -1
  2. if gas2 > 0 ,记下当前索引重新拼接这个数组,遍历一遍中间不能小于0
class Solution(object):
    def canCompleteCircuit(self, gas, cost):
        """
        :type gas: List[int]
        :type cost: List[int]
        :rtype: int
        """
        for i in range(len(gas)):
            gas[i] -= cost[i]

        if sum(gas) < 0:
            return -1

        for i in range(len(gas)):
            if gas[i] >= 0:

                new_gas = gas[i:] + gas[:i]

                cursum = 0
                flag = i
                for j in range(0,len(new_gas)):

                    if cursum + new_gas[j] < 0:
                        break
                        
                    elif j == len(new_gas) - 1:
                        return flag
                    else:
                        cursum += new_gas[j]

别人的

# -*- coding:utf-8 -*-
class Solution(object):
    def canCompleteCircuit(self, gas, cost):
        """
        :type gas: List[int]
        :type cost: List[int]
        :rtype: int
        """
        # 0 到 start的油量
        total = 0
        # 从起始位置到i的油量
        tank = 0
        # 记录加油的位置
        start = 0
        
        for i in range(len(gas)):
            
            tank += gas[i] - cost[i]
            
            if tank < 0:
                total += tank
                tank = 0
                start = i + 1
                
        if total + tank >=0:
            return start
        else:
            return -1

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

我的思路

分类讨论:
使用栈的方法,比较大小,然后计数
注意特例:
输入[1] 和 [1]

# -*- coding:utf-8 -*-
import sys
class Solution(object):
    def findMedianSortedArrays(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: float
        """
        if len(nums1) == 1 and len(nums2) == 1:
            return (nums1[0] + nums2[0]) / 2
        lenght = len(nums1) + len(nums2)

        if lenght % 2 == 0:
            mid_o = int(lenght / 2)
            i = 0
            n1 = sys.maxsize
            n2 = sys.maxsize
            while nums1 or nums2:

                if nums1 and n1 == sys.maxsize:
                    n1 = nums1.pop(0)

                if nums2 and n2 == sys.maxsize:
                    n2 = nums2.pop(0)

                if n1 < n2:
                    i += 1
                    if i == mid_o:
                        a = n1
                        n1 = sys.maxsize
                    elif i == mid_o + 1:
                        b = n1
                        return float((a+b) / 2)
                    else:
                        n1 = sys.maxsize
                else:
                    i += 1
                    if i == mid_o:
                        a = n2
                        n2 = sys.maxsize
                    elif i == mid_o + 1:
                        b = n2
                        return float((a+b) / 2)
                    else:
                        n2 = sys.maxsize


        else:
            mid_j = int(lenght / 2) + 1
            i = 0
            n1 = sys.maxsize
            n2 = sys.maxsize
            while nums1 or nums2:

                if nums1 and n1 == sys.maxsize:
                    n1 = nums1.pop(0)

                if nums2 and n2 == sys.maxsize:
                    n2 = nums2.pop(0)

                if n1 < n2:
                    i += 1
                    if i == mid_j:
                        return float(n1)
                    else:
                        n1 = sys.maxsize
                else:
                    i += 1
                    if i == mid_j:
                        return float(n2)
                    else:
                        n2 = sys.maxsize

递归

112.路径总和

链接

# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    def hasPathSum(self, root, sum):
        """
        :type root: TreeNode
        :type sum: int
        :rtype: bool
        """
        if not root:
            return False

        sum -= root.val

        # 叶子结点的判断条件
        if not root.left and not root.right:
            return sum == 0

        return self.hasPathSum(root.left,sum) or self.hasPathSum(root.right,sum)

哈希

两数之和

思路

用哈希存下数组每个元素并记录其index
遍历一遍数组,查找是否存在 target - nums[i],有的话返回i和该哈希值

class Solution(object):
    def twoSum(self, nums,target):
        nums_dict = {}
        for index,val in enumerate(nums):
            nums_dict[val] = index
        for ind,n in enumerate(nums):
            j = nums_dict.get(target - n)
            if j and ind != j:
                return [ind,j]

1160. 拼写单词

class Solution(object):
    def countCharacters(self, words, chars):
        """
        :type words: List[str]
        :type chars: str
        :rtype: int
        """
        ## Counter['item'] 不存在会返回0
        ans = 0
        char_dict = str2dict(chars)
        for w in words:
            w_dict = str2dict(w)
            for key,val in w_dict.items():
                
                if key not in char_dict.keys():
                    break
                if char_dict[key] - w_dict[key] < 0:
                    break
            #for else用法
            else:
                ans += len(w)
        return ans
            
def str2dict(s):
    s_dict = {}
    for i in s:
        s_dict[i] = s_dict.get(i,0) + 1
    return s_dict   

方法二

class Solution:
    def countCharacters(self, words: List[str], chars: str) -> int:
        ans = 0
        cnt = collections.Counter(chars)
        for w in words:
            c = collections.Counter(w)
            if all([c[i] <= cnt[i] for i in c]):
                ans += len(w)
        return ans
  • for else使用
  • 可以用collections.Counter来代替字典,Counter[‘item’] 不存在会返回0

动态规划

面试题 17.16. 按摩师

思路

动态规划
cur = 0
pre = 0
res = max(cur,pre + nums[i])

class Solution(object):
    def massage(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        pre = 0
        cur = 0
        res = 0

        for i in nums:
            res = max(cur,pre + i)
            pre = cur
            cur = res
        return res

面试题42. 连续子数组的最大和

给定一个整数数组(有正数有负数),找出总和最大的连续数列,并返回总和。
示例:
输入: [-2,1,-3,4,-1,2,1,-5,4]
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。

class Solution(object):
    def maxSubArray(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        cur = nums[0]
        max_sum = nums[0]
        for i in range(1,len(nums)):
            if cur <= 0:
                cur = nums[i]
            else:
                cur += nums[i]
            ##
            if cur > max_sum:
                max_sum = cur
        return max_sum

152. 乘积最大连续子序列

思路:

  • 1、初始化最大值为负无穷,当前最大值max_cur为1,当前最小值min_cur为1
  • 2、max_cur更新max(max_cur*nums[i],nums[i])
  • 3、min_cur更新min(min_cur*nums[i],nums[i])
  • if nums[i]为负数,max_cur和min_cur要互换
  • max_res更新max(max_res,max_cur)
import sys
class Solution(object):
    def maxProduct(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """ 
        max_cur = 1
        min_cur = 1
        max_res = -sys.maxsize
        
        for i in nums:
            if i < 0:
                tmp = max_cur
                max_cur = min_cur
                min_cur = tmp
                
            max_cur = max(max_cur * i,i)
            min_cur = min(min_cur *i,i)
            max_res = max(max_res,max_cur)
        return max_res

300. 最长上升子序列

思路:

  • 1、先判断nums是不是空的
  • 2、令dp数组为1
  • 3、i ~ range(len(nums)) : j ~ range(i)
  •   状态转移方程 dp[i] = max(dp[i],dp[j]+1)
    
  • return max(dp)
class Solution(object):
    def lengthOfLIS(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        if not nums:
            return 0
        
        dp = [1] * len(nums)
        
        for i in range(len(nums)):
            for j in range(i):
                
                if nums[j] < nums[i]:
                    dp[i] = max(dp[i],dp[j] + 1)
        return max(dp)

334.递增的三元子序列

我的思路

上一题树递增的子序列的长度,所以直接搬过来,判断长度是否大于三即可

class Solution(object):
    def increasingTriplet(self, nums):
        """
        :type nums: List[int]
        :rtype: bool
        """
        if not nums:
            return False
        dp = [1] * len(nums)
        for i in range(len(nums)):
            for j in range(i):
                if nums[j] < nums[i]:
                    dp[i] = max(dp[i],dp[j] + 1)
                    if dp[i] >= 3:
                        return True
        return False

别人思路-双指针

能跳到第二个小的,说明前面保存两个小的,跳到第三个就是三个递增子序列

class Solution(object):
    def increasingTriplet(self, nums):
        """
        :type nums: List[int]
        :rtype: bool
        """
        min1 = sys.maxsize
        min2 = sys.maxsize

        for i in nums:
            if min1 >= i:
                min1 = i
            elif min2 >= i:
                min2 = i
            else:
                return True
        return False

322. 零钱兑换

思路:
i

import sys
class Solution(object):
    def coinChange(self, coins, amount):
        """
        :type coins: List[int]
        :type amount: int
        :rtype: int
        """
        dp = [sys.maxsize] * (amount + 1)
        ## 这一步很关键,要不然无法min + 1
        dp[0] = 0
        for c in coins:
            for i in range(c,len(dp)):
                dp[i] = min(dp[i],dp[i-c]+1)
        return dp[amount] if dp[amount] != sys.maxsize else -1

279.完全平方数

类似零钱兑换,但是python会超时

要将j的遍历区间变为[1,int(sqrt(i))+1):

class Solution(object):
    def numSquares(self, n):
        """
        :type n: int
        :rtype: int
        """
        dp = [i for i in range(n+1)]
        for i in range(2,n+1):
            for j in range(1,int(i**(0.5))+1):
                dp[i] = min(dp[i],dp[i-j*j]+1)
        return dp[-1]

121.买卖股票的最佳时机

思路

找到最小的值,然后跟当前的maxprofit比较,然后更新

import sys 

class Solution(object):
    def maxProfit(self, prices):
        """
        :type prices: List[int]
        :rtype: int
        """
        max_profit = 0
        min_val = sys.maxsize
        
        for i in prices:
            
            if i < min_val:
                min_val = i
                
            elif i - min_val > max_profit:
                
                max_profit = i - min_val
                
        return max_profit

122.买卖股票的最佳时机II

思路

直接前后做差,相加差大于即可得到。

class Solution(object):
    def maxProfit(self, prices):
        """
        :type prices: List[int]
        :rtype: int
        """
        for i in range(1,len(prices)):
            
            prices[i-1] = prices[i] - prices[i-1]
        
        max_profit = 0

        for i in range(len(prices)-1):
            
            if prices[i] > 0:
                max_profit += prices[i]
                
        return max_profit

##746. 使用最小花费爬楼梯

class Solution:
    def minCostClimbingStairs(self, cost: List[int]) -> int:

        cost = [0,0] + cost
            
        for i in range(2,len(cost)):
            
            cost[i] = min(cost[i-1], cost[i-2]) + cost[i]
            
        l = len(cost)    
        if cost[l-1] > cost[l-2]:
            return cost[l-2]
        else:
            return cost[l-1]

1143.最长公共子序列

链接

思路

在这里插入图片描述
注意赋值为0
在这里插入图片描述

class Solution(object):
    def longestCommonSubsequence(self, text1, text2):
        """
        :type text1: str
        :type text2: str
        :rtype: int
        """
        m = len(text1) + 1
        n = len(text2) + 1
        
        # dp = [[0] * m] * n有个坑,改变一个值会改变整一列
        dp = [[0] * m for i in range(n)]
        
        for i in range(1,n):
            for j in range(1,m):
                
                if text1[j-1] == text2[i-1]:
                    dp[i][j] = dp[i-1][j-1] + 1
                    
                else:
                    dp[i][j] = max(dp[i-1][j],dp[i][j-1])
                    
        return dp[n-1][m-1]

数学

365.水壶问题

看题解:
取xy的最大公约数,看z是否能整除
注意边界条件:
1、x + y < z
2、x = 0或y=0
只有python3才有gcd函数

class Solution:
    def canMeasureWater(self, x,y,z):

        if x + y < z:
            return False
        if x == 0 or y == 0:
            return z == 0 or x + y == z
        return z % math.gcd(x, y) == 0

双指针

392.判断子序列

class Solution(object):
    def isSubsequence(self, s, t):
        """
        :type s: str
        :type t: str
        :rtype: bool
        """

        i = 0
        j = 0

        while i < len(s) and j < len(t):

            if s[i] == t[j]:
                i += 1
                j += 1
            else:
                j+=1
                
        return i == len(s)

11.盛最多水的容器

我的思路

双指针解法,哪边小,更新哪边指针。

class Solution(object):
    def maxArea(self, height):
        i = 0
        j = len(height) - 1
        res = 0
        while i < j:
            if height[i] > height[j]:
                width = height[j]
                length = j - i
                j -= 1
            else:
                width = height[i]
                length = j - i
                i += 1
            
            area = length * width

            if area > res:
                res = area

        return res

贪心

135.分发糖果

题解
将左右规则拆分为左规则和右规则,取两个数组的最大值。
Alt

class Solution(object):
    def candy(self, ratings):
        """
        :type ratings: List[int]
        :rtype: int
        """
        left2right = [1] * len(ratings)
        right2left = [1] * len(ratings)

        for i in range(1,len(ratings)):

            if ratings[i] > ratings[i-1]:
                left2right[i] = left2right[i-1] + 1

        for i in reversed(range(0,len(ratings)-1)):

            if ratings[i] > ratings[i+1]:
                right2left[i] = right2left[i+1] + 1

        for i in range(len(ratings)):
            if left2right[i] < right2left[i]:
                left2right[i] = right2left[i]

        return sum(left2right)

滑动窗口

3.无重复字符的最长子串

思路

其实就是一个队列,比如例题中的 abcabcbb,进入这个队列(窗口)为 abc 满足题目要求,当再进入 a,队列变成了 abca,这时候不满足要求。所以,我们要移动这个队列!

如何移动?

我们只要把队列的左边的元素移出就行了,直到满足题目要求!

一直维持这样的队列,找出队列出现最长的长度时候,求出解!

class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        s_list = []
        res = 0
        for i in s:
            if i in s_list:
                if len(s_list) > res:
                    res = len(s_list)
                    
                while s_list.pop(0) != i:
                    continue
                
                s_list.append(i)
            else:
                s_list.append(i)
                
        if len(s_list) > res:
            res = len(s_list)
                    
        return res
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值