alex_bn_lee

导航

【700】Leecode solution

 001. 两数之和

2022年7月12日

【分析】最简单的想法就是两层遍历,时间复杂度为 $O(n^2)$。为了提高效率因此不能进行两层遍历,第一层的遍历是必须的,针对每一个元素,考虑 target-nums[i] 是否在数组里面。因为最终的结果需要索引值,因此考虑到将 nums 的元素作为 key,索引作为 value 来构建 哈希表(字典),从而可以根据数值获取对应的索引值!

【总结】哈希表的灵活使用很重要,特别是涉及到索引的问题,重要函数 hashmap.get(key),如果找到,则返回对应的值,如果找不到,则返回 None。

 

002. 两数相加

2022年7月13日 

【分析】主要是考察链表,根据已经定义好的链表class来直接用。注意不同链表的不同处理情况!

【总结】链表就是逻辑性很强,但是不难

Python实现链表操作

(1)定义 ListNode

查看代码
 class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

(2)将list转为链表

查看代码
 def create_list_node(list1):
    """
    把list转为链表
    """
    head = ListNode()   # 头结点,设置为空
    loop_node = head    # 循环结点
    for e in list1:     # 通过循环构建新的结点,并连接起来
        tmp_node = ListNode(e)
        loop_node.next = tmp_node
        loop_node = tmp_node
        
    return head.next    # 最终返回头结点的下一个结点即可

(3)将链表转为list

查看代码
 def print_list_node(l1):
    """
    把链表转为list
    """
    arr = []
    while l1:
        arr.append(l1.val)
        l1 = l1.next
        
    return arr

最终代码:

查看代码
 # Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
        # 定义一个头结点
        l3 = ListNode()
        # 定义一个指针
        p = l3
        # 定义进位值
        flag = 0
        # 针对不同的情况分别考虑
        while l1 != None or l2 != None:
            if l1 == None:
                s = l2.val + flag
                flag = 0
                if s > 9:
                    s = s % 10
                    flag = 1
                l2 = l2.next
            elif l2 == None:
                s = l1.val + flag
                flag = 0
                if s > 9:
                    s = s % 10
                    flag = 1
                l1 = l1.next
            else:
                s = l1.val + l2.val + flag
                flag = 0
                if s > 9:
                    s = s % 10
                    flag = 1
                l1 = l1.next
                l2 = l2.next
            tmp_node = ListNode(s) 
            p.next = tmp_node
            p = p.next 

        if flag == 1:
            tmp_node = ListNode(1)
            p.next = tmp_node

        return l3.next 

 

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

查看代码
 class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        tmp = ""
        max_length = 0 
        for e in s:
            if e not in tmp:
                tmp += e 
            else:
                ind = tmp.find(e)
                tmp = tmp[(ind+1):] + e 
                   
            if len(tmp) > max_length:
                max_length = len(tmp)
                
        return max_length

 

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

 

005. 最长回文子串

  • 暴力解法:遍历每一个字符,然后两边扩散

  • 动态规划:构建二维数组,参考讲解答案

方法一:暴力解法

查看代码
 class Solution:
    def longestPalindrome(self, s: str) -> str:
        max_len = 0 
        max_str = ""

        for i in range(len(s)):
            i_r = i 
            for k in range(1, len(s)-i):
                if s[i+k] != s[i]:
                    i_r = i + k-1
                    break
                if k == len(s) - i - 1:
                    i_r = len(s) 

            length = i_r - i + 1
            if length > max_len:
                max_len = length
                max_str = s[i:i_r+1]      

            for j in range(min(i+1, len(s)-i_r)):
                if s[i-j] != s[i_r+j]:
                    length = 2*j-2 + i_r - i + 1
                    if length > max_len:
                        max_len = length
                        max_str = s[i-j+1:i_r+j] 
                    break
                if j == min(i+1, len(s)-i_r) - 1:
                    length = 2*j + i_r - i + 1
                    if length > max_len:
                        max_len = length
                        max_str = s[i-j:i_r+j+1] 

        return max_str

方法二:动态规划

查看代码
 class Solution:
    def longestPalindrome(self, s: str) -> str:
        if len(s) == 0: return ""

        dp = [[False] * len(s) for i in range(len(s))]

        for i in range(len(s)):
            dp[i][i] = True 

        max_len = 1
        max_str = s[0]

        for j in range(1, len(s)):
            for i in range(j):
                if s[i] == s[j] and (j-i<3 or dp[i+1][j-1]):
                    dp[i][j] = True 
                    if j - i + 1 > max_len:
                        max_len = j - i
                        max_str = s[i:j+1]
                    
        return max_str

 

006. Z 字形变换

  • 分别考虑两种情况,一种是一列上面都是满的,一种情况就是一列只有一个元素
查看代码
 class Solution:
    def convert(self, s: str, numRows: int) -> str:
        if numRows == 1: return s 

        arr = [[""] * len(s) for i in range(numRows)]

        ind = 0 

        # 需要注意的是,二维数组是[row][column]形式的,所以赋值的时候
        # 注意是arr[j][i],不要弄反了!
        for i in range(len(s)):
            if ind == len(s): break

            # 能整除的列,全部遍历显示    
            if i % (numRows - 1) == 0:
                for j in range(numRows):
                    if ind == len(s): break 
                    arr[j][i] = s[ind] 
                    ind += 1
                    if ind == len(s): break

            # 不能整除的列,只显示一个位置,通过归纳找到对应的索引值            
            if i % (numRows - 1) != 0:
                if ind == len(s): break 
                ind_j = numRows - 1 - i % (numRows - 1)
                arr[ind_j][i] = s[ind]
                ind += 1
                if ind == len(s): break 

        return ''.join([''.join(arr[i]) for i in range(numRows)])

 

007. 整数反转

  • 可以直接通过字符串反转来实现

  • 可以通过十进制的规律来获取每一位的数字,再反向组成数字

方法一:

查看代码
 class Solution:
    def reverse(self, x: int) -> int:
        if x==0: return 0

        tmp = (x//abs(x)) * int(str(abs(x))[::-1])

        if tmp < -2**31 or tmp > 2**31-1:
            return 0

        return tmp 

方法二:

查看代码
 class Solution:
    def reverse(self, x: int) -> int:
        if x==0: return 0

        if x > 0: x_tmp = x 
        if x < 0: x_tmp = -1 * x 
        
        num_arr = []
        while x_tmp > 0: 
            num_arr.append(x_tmp % 10)
            x_tmp = x_tmp // 10
            
        num = 0 
        carry = 1
        for i in range(len(num_arr)-1, -1, -1):
            num += num_arr[i] * carry
            carry *= 10

        if x < 0: num = -1 * num 

        if num < -2**31 or num > 2**31-1:
            return 0

        return num  

 

008. 字符串转换整数 (atoi)

  • 主要考虑规则

    • 首先去掉前面空格

    • 连续的可以作为数字才考虑

    • "+-200-+300" 返回 0 

代码中使用了try...except...来完成报错情况的结果输出,整体的代码就是一边调试一边修改,因为对具体的规则不了解!

查看代码
 class Solution:
    def myAtoi(self, s: str) -> int:
        s = s.strip() 
        if s=="": return 0 
        ref = ["+", "-", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0"]

        if s[0] not in ref: return 0

        s_cut = ""
        for i in range(len(s)):
            if s[i] not in ref:
                s_cut = s[:i]
                break
            if i == len(s)-1:
                s_cut = s 

        flag = 0 
        for i in range(len(s_cut)):
            if s_cut[i] not in ["+", "-"]:
                flag = 1 

            if flag and s_cut[i] in ["+", "-"]:
                s_cut = s_cut[:i]
                break 

        try:
            res = int(s_cut)
        except:
            return 0

        if int(s_cut) < -1 * 2 ** 31:
            return -1 * 2 ** 31
        if int(s_cut) > 2 ** 31 - 1:
            return  2 ** 31 - 1

        return int(s_cut)

 

011. 盛最多水的容器

  • 可以通过动态规划的思想来解答,但是会超时,动态规划时间复杂度过高
  • 通过设置leftright两个指针,然后根据情况进行左右移动,效率更高

查看代码
 class Solution:
    def maxArea(self, height: List[int]) -> int:
        # 时间复杂度过大,无法通过
        #dp = [0] * (len(height) + 1)
        #dp[2] = min(height) 

        #for i in range(3, len(height) + 1):
        #    dp[i] = max(dp[i-1], max([(i-1-j)*min(height[j], height[i-1]) for j in range(i-1)]))

        #return dp[-1]
        
        # 下面为双指针方法
        left = 0
        right = len(height) - 1
        maxA = 0 

        while left < right: 
            tmp = (right - left) * min(height[left], height[right])
            if maxA < tmp: maxA = tmp 
            if height[left] < height[right]:
                left += 1
            else:
                right -= 1

        return maxA

 

012. 整数转罗马数字

  • 利用穷举的方法来实现!
查看代码
 class Solution:
    def intToRoman(self, num: int) -> str:
        res = ""
        if num // 3000 > 0: 
            num %= 3000 
            res += "MMM"
        if num // 2000 > 0: 
            num %= 2000 
            res += "MM"
        if num // 1000 > 0: 
            num %= 1000
            res += "M"
        if num // 900 > 0:
            num %= 900
            res += "CM"
        if num // 500 > 0:
            num %= 500 
            res += "D"
        if num // 400 > 0:
            num %= 400 
            res += "CD"
        if num // 300 > 0:
            num %= 300
            res += "CCC"
        if num // 200 > 0:
            num %= 200
            res += "CC"
        if num // 100 > 0:
            num %= 100
            res += "C"
        if num // 90 > 0:
            num %= 90
            res += "XC"
        if num // 50 > 0:
            num %= 50
            res += "L"
        if num // 40 > 0:
            num %= 40
            res += "XL"
        if num // 30 > 0:
            num %= 30
            res += "XXX"
        if num // 20 > 0:
            num %= 20
            res += "XX"
        if num // 10 > 0:
            num %= 10
            res += "X"
        if num // 9 > 0:
            num %= 9
            res += "IX"
        if num // 5 > 0:
            num %= 5
            res += "V"
        if num // 4 > 0:
            num %= 4
            res += "IV"
        if num // 3 > 0:
            num %= 3
            res += "III"
        if num // 2 > 0:
            num %= 2
            res += "II"
        if num // 1 > 0:
            num %= 1
            res += "I"
            
        return res

 

 

 

 

【分析】

【总结】

 

15. 三数之和

  可以通过双指针的方式来降低时间复杂度!

查看代码
 class Solution:
    def threeSum(  self , nums:   List [  int ])   - >   List [  List [  int ]]:
        arr   = []
        length   = len (nums)
        nums.sort() 

        for i   in range (length  - 2 ):
            if nums[i] >   0 :   break
            if i >   0 and nums[i]   = = nums[i  - 1 ]:   continue
            left   = i   + 1
            right   = length   - 1
            while left < right:
                s   = nums[i]   + nums[left]   + nums[right]
                if s   = = 0 :
                    arr.append([nums[i], nums[left], nums[right]])
                    left   + = 1
                    right   - = 1
                    while (left < right   and nums[left]   = = nums[left   - 1 ]): left   + = 1
                    while (left < right   and nums[right]   = = nums[right   + 1 ]): right   - = 1
                elif s <   0 :
                    left   + = 1
                    while (left < right   and nums[left]   = = nums[left   - 1 ]): left   + = 1
                else :
                    right   - = 1
                    while (left < right   and nums[right]   = = nums[right   + 1 ]): right   - = 1

        return arr

 

 

  

016. 最接近的三数之和

  可以通过双指针的方式来降低时间复杂度!

查看代码
 class Solution:
    def threeSumClosest(      self , nums:       List [      int ], target:       int )       - >       int :
        nums.sort()
        res       = nums[      0 ]       + nums[      1 ]       + nums[      - 1 ]
        gap       = abs (res       - target)

        for i       in range (      len (nums)       - 2 ):
            if nums[i] >       0 and nums[i] > target:       break
            left       = i       + 1
            right       = len (nums)       - 1

            while (left < right):
                s       = nums[i]       + nums[left]       + nums[right]
                if s       = = target:
                    return target
                elif s < target:
                    if target       - s < gap:
                        gap       = target       - s
                        res       = s 
                    left       + = 1
                else :
                    if s       - target < gap:
                        gap       = s       - target
                        res       = s 
                    right       - = 1

        return res

  

017. 电话号码的字母组合

  使用动态规划的方法来解决!

查看代码
 class Solution:
    def letterCombinations(      self , digits:       str )       - >       List [      str ]:
        if not digits:       return []
        hashmap       = {      "2" :       "abc" ,       "3" :       "def" ,       "4" :       "ghi" ,       "5" :       "jkl" , 
                   "6" :       "mno" ,       "7" :       "pqrs" ,       "8" :       "tuv" ,       "9" :       "wxyz" }
        dp       = [[]       for i       in range (      len (digits)       + 1 )]
        dp[      1 ]       = [e       for e       in hashmap[digits[      0 ]]]

        for i       in range (      2 ,       len (digits)      + 1 ):
            arr       = []
            for e1       in dp[i      - 1 ]:
                for e2       in hashmap[digits[i      - 1 ]]:
                    arr.append(e1      + e2)
            dp[i]       = arr 

        return dp[      - 1 ]

 

18. 四数之和

  双指针的方法!

367. 有效的完全平方数

解决方案:对于已经排好序的遍历问题,可以优先考虑二分法!

查看代码
 class Solution:
    def isPerfectSquare(self, num: int) -> bool:
        if num == 1: return True 

        #for i in range(num//2+1):
        #    if i * i == num:
        #        return True
        #    elif i * i > num:
        #        return False 

        #return False

        left = 1
        right = num//2 + 1

        while (left <= right):
            mid = (left + right) // 2

            if mid * mid == num:
                return True 
            if mid * mid < num:
                left = mid + 1
            else:
                right = mid - 1

        return False 

 

posted on 2022-05-13 15:31  McDelfino  阅读(37)  评论(0)    收藏  举报