leetcode 1-100 medium难度题目汇总

写在前面

近半个月的整理, 终于完成了前一百题的easy和medium题目的分析 😅 秋招已经开始了, 祝自己好运 😇 以后有空逐渐把hard补上 😎

文章目录

2. Add Two Numbers (Medium)

题目描述

给两个链表, 做加法

Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8
Explanation: 342 + 465 = 807.

解题思路

"""
类似于合并两个链表
1. 依顺序把l2的元素加到l1中
2. 当一个链表已经加完, 接下来做的就是把进位和剩下的链表加和
3. 当两个链表长度相等, 要判断最后一个节点值是否大于10, 可能产生进位值
4. 当遍历完所有节点后, 如果仍有进位值, 则加入一个新节点
"""
class Solution:
    def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
        head = l1
        carry = 0
        while l1 or l2:
            
            if l1 and l2:
                s = l1.val + l2.val + carry
                l1.val = s%10 
                carry = s//10
                last = l1 # 如果l1为空, 把最后一个node指l2
                l1 = l1.next
                l2 = l2.next
                
            elif l1: # l1比l2长
                s = l1.val + carry # 补全进位
                l1.val = s%10 
                carry = s//10
                if carry == 0: # 如果不再有进位, 提前终止加和.
                    break
                last = l1
                l1 = l1.next
                
            elif l2: # l1比l2短
                last.next = l2
                s = l2.val + carry
                l2.val = s%10 
                carry = s//10
                if carry == 0:
                    break
                last = l2
                l2 = l2.next
                
        if last.val >= 10:
            last.val = last.val % 10
            carry = 1
        if carry: #如果carry有值需要加入一个新节点.
            last.next = ListNode(1)
        return head
                

3. Longest Substring Without Repeating Characters (Medium)

https://leetcode.com/problems/longest-substring-without-repeating-characters/
题目描述

给一个字符串, 返回最长的没有重复元素的子串.

Input: "abcabcbb"
Output: 3 
Explanation: The answer is "abc", with the length of 3.

解题思路

"""
设置一个滑动窗口.
每次右边界滑动一个位置, check左边界是否会重复, 如果重复了, 左边界向右滑动, 直到左边界的字符不等于右边界位置上的字符未知.
每次移动结束后, check当前窗口长度.
"""
class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        if s == '':
            return 0
        start = end = result = 0
        while end < len(s):
            if s[end] not in s[start:end]:
                end += 1
                result = max(result, end-start)
            else:
                start = start + s[start:end].find(s[end]) + 1 #return the index of s[end] in s[start:end]
                end += 1
        return result

5. Longest Palindromic Substring (Medium)

题目描述

给一个字符串, 找到最长的回文子字符串.

Input: "babad"
Output: "bab"
Note: "aba" is also a valid answer.

解题思路

"""
遍历所有节点.
	1. 从当前节点, 向两边遍历, 直到元素不相等为止. 得到一个回文字符串.
	2. check当前回文字符串
注意原字符串的奇偶长度
"""
class Solution:
    def longestPalindrome(self, s: str) -> str:
        Max = 0
        longest = ''
        for i in range(len(s)):

            #odd case, like'aba'
            subStr = self.helper(s, i, i)
            if len(subStr) >= Max:
                Max = len(subStr)
                longest = subStr
                
            #even case, like'abba'
            subStr = self.helper(s, i, i+1)
            if len(subStr) >= Max:
                Max = len(subStr)
                longest = subStr 
                
        return longest

    def helper(self, s, start, end):   
        subStr = ''
        while start >= 0 and end <len(s) and s[start] == s[end]:
            subStr = s[start:end+1]
            start -= 1
            end += 1
        return subStr

6. ZigZag Conversion (Medium)

题目描述

字符串 “PAYPALISHIRING"以Z形走法书写, 逐行输出结果为"PAHNAPLSIIGYIR”

P   A   H   N
A P L S I I G
Y   I   R

设计转换函数.

解题思路

# 倒着的Z字拼接在一起,先找组成Z字的规律
'''
(*      *) 虽然是z型看起来复杂,其实简单,走势符合直下斜上的顺序
*     * *  创建五个存储空间来保存每次走过的字母即可。
*   *   *
* *     *
*       * 
'''
class Solution:
    def convert(self, s: str, numRows: int) -> str:
        # 特殊情况,字符只够摆第一竖列
        if numRows == 1 or numRows >= len(s):
            return s
        L = [''] * numRows
        index = 0
        # step往下走,当step=-1即回头,往上走
        for x in s:
            L[index] += x
            if index == 0: step = 1
            if index == numRows - 1: step = -1
            index += step
        return ''.join(L)

8. String to Integer (atoi) (Medium)

https://leetcode.com/problems/string-to-integer-atoi/
题目描述

解题思路

class Solution:
    def myAtoi(self, s: str) -> int:
        if s == '':
            return 0
        # 将字符串去掉空格保存在列表中,只要研究列表第一个元素即可
        s2 = s.strip().split(' ')[0]
        # 仍然需要判断一次,不然报错
        if s2 == '':
            return 0
        
        flag = 1
        num = {
   '1','2','3','4','5','6','7','8','9','0'}
        
        #保存符号
        if s2[0] == '-':
            flag = -1
            s2 = s2[1:]
        elif s2[0] == '+':
            s2 = s2[1:]
        # 临界判断, 太重要了!单独一个字符'+'或'-'
        if s2 == '':
            return 0
            
        # 首字符是字母返回0
        if s2[0] not in num:
            return 0
        # 后面如果跟字母要想办法去掉
        for i in s2:
            if i not in num:
                index = s2.index(i)
                s2 = s2[:index]
                break
        
        s2 = flag * int(s2)
        
        if s2 > 2**31 - 1:
            return 2**31 - 1
        elif s2 < -(2**31):
            return -(2**31)
        
        return s2

11. Container With Most Water (Medium)

https://leetcode.com/problems/container-with-most-water/
题目描述

给一个数组, 每个数字代表隔板长度, 确定能容纳水的最大体积.
在这里插入图片描述

Input: [1,8,6,2,5,4,8,3,7]
Output: 49

解题思路

"""
短的隔板决定容器的高度.
设置两个指针, 分别从头尾向中间移动.
	1.如果头指针大于尾指针, 则尾指针向头部移动.
	2.如果头指针小于尾指针, 则头指针向尾部移动.
	3.每次移动完, check当前容积.
"""
class Solution:
    def maxArea(self, height: List[int]) -> int:
        result = 0
        start = 0
        end = len(height)-1
        while start < end:
            result = max(result, min(height[start], height[end]) * (end - start))
            #将两条线往对方方向走。
            if height[start] < height[end]:
                start += 1
            else:
                end -= 1
        return result

12. Integer to Roman (Medium)

https://leetcode.com/problems/integer-to-roman/
题目描述

把罗马数字转换成十进制数字.

解题思路

class Solution:
    def intToRoman(self, num: int) -> str:
        value_roman = {
   1000:"M", 900:"CM", 500:"D", 400:"CD",
                       100:"C", 90:"XC", 50:"L", 40:"XL",
                       10:"X", 9:"IX", 5:"V", 4:"IV", 1:"I"}
        roman = ""
        for v in [1000,900,500,400,100,90,50,40,10,9,5,4,1]:
            roman += value_roman[v] * (num//v)
            num %= v
        return roman

15. 3Sum (Medium) **

https://leetcode.com/problems/3sum/
题目描述

给定一个数组, 找到有所能使得和为0的组合. 组合不能重复.

Given array nums = [-1, 0, 1, 2, -1, -4],
A solution set is:
[ [-1, 0, 1], [-1, -1, 2] ]

解题思路

"""
动态规划
先将数组排序. 
从头开始逐个元素遍历, 位置为i, 左指针指向i+1, 右指针指向tail.
当 左指针 < 右指针 时:
	1. 加和三个指针指向的值.
	2. 和大于0, 说明和需要减小, 右指针左移一个位置(因为数组有序, 右边数大于左边)
	3. 和小于0, 说明和需要增大. 左指针右移一个位置
	4. 当和等于0时, 继续移动左右指针去掉与当前值相同的元素
"""
class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:        
        if len(nums) <3: # deal with special input
            return []
        elif len(nums) == 3:
            if sum(nums) == 0:
                return [sorted(nums)]
            
        res = []
        nums.sort()
        for i in range(len(nums)-2):
            if i > 0 and nums[i] == nums[i-1]:
                continue
            l, r = i+1, len(nums)-1            
            while l < r:
                s = nums[i] + nums[l] + nums[r]
                if s < 0:
                    l +=1 
                elif s > 0:
                    r -= 1
                else:
                    res.append((nums[i], nums[l], nums[r]))
                    while l < r and nums[l] == nums[l+1]:
                        l += 1
                    while l < r and nums[r] == nums[r-1]:
                        r -= 1
                    l += 1; r -= 1
        return res

16. 3Sum Closest (Medium)

https://leetcode.com/problems/3sum-closest/
题目描述

同上一题, 只是给定一个target, 找出同target最接近的值.

解题思路

"""
同上一题, 三个指针.
"""
class Solution:
    def threeSumClosest(self, nums, target):
        nums.sort()
        res = sum(nums[:3])
        for i in range(len(nums)):
            l, r = i+1, len(nums)-1
            while l < r:
                s = sum((nums[i], nums[l], nums[r]))
                if abs(s-target) < abs(res-target):
                    res = s
                if s < target:
                    l += 1
                elif s > target:
                    r -= 1
                else: # break early 
                    return res
        return res  

17. Letter Combinations of a Phone Number (Medium)

https://leetcode.com/problems/letter-combinations-of-a-phone-number/
题目描述
在这里插入图片描述
输入数字字符串, 输出可能的字母组合. (九宫格按键)

Input: "23"
Output: ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].

解题思路
递归

"""

"""
class Solution:
    def letterCombinations(self, digits: str) -> List[str]:
        if digits == "":
            return []
        mapp = {
   '2': 'abc', 
                '3': 'def', 
                '4': 'ghi', 
                '5': 'jkl', 
                '6': 'mno', 
                '7': 'pqrs', 
                '8': 'tuv', 
                '9': 'wxyz'}
        res = []
        self.combinate(digits, mapp, 0, len(digits), '', res)
        return res
    
    def combinate(self, s, mapp, n, m, path, res):
        if n == m:
            res.append(path)
            return 
        for i in mapp[s[n]]:
            self.combinate(s, mapp, n+1, m, path+i, res) 

非递归做法

class Solution:
    def letterCombinations(self, digits: str) -> List[str]:
        pad = {
   
            '2': 'abc',
            '3': 'def',
            '4': 'ghi',
            '5': 'jkl',
            '6': 'mno',
            '7': 'pqrs',
            '8': 'tuv',
            '9': 'wxyz'
        }
        if not digits:
            return []
        output = ['']
        for digit in digits:
            temp = output
            output = []
            for s in temp:
                output.extend([s + pad[digit][0], s + pad[digit][1], s+ pad[digit][2]])
                if digit == '7' or digit == '9':
                    output.append(s + pad[digit][3])
                    
        return output

18. 4Sum (Medium)

https://leetcode.com/problems/4sum/
题目描述

同3Sum, 只是改为四个数和为0.

解题思路

"""
3Sum的拓展
在4Sum中将0-当前数作为target传入3Sum函数
"""
class Solution:
    def fourSum(self, nums, target):
        results = []
        nums.sort()
        for i in range(len(nums)-3):
            if i == 0 or nums[i] != nums[i-1]:
                threeResult = self.threeSum(nums[i+1:], target-nums[i])
            for item in threeResult:
                results.append([nums[i]] + item)
        return results

    def threeSum(self, nums, target):
        results = []
        nums.sort()
        for i in range(len(nums)-2):
            l = i + 1; r = len(nums
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值