leetcode系列1 1-10

  1. 两数之和
    解题思路:通过新建一个字典将list中的数进行重新存储,数字作为key,索引值作为value,如果已经满足条件就返回,不满足条件就讲数据存到字典中。
#
# @lc app=leetcode id=1 lang=python3
#
# [1] Two Sum
#
# @lc code=start
class Solution:
    def twoSum(self, nums, target) :
        index = {}
        for i, x in enumerate(nums):
            if target - x in index:
                return [index[target - x], i]
            index[x] = i
  1. Add Two Numbers

思路:首先将两个链表中的元素存到一个string中,再将string中的元素存到列岸标中。

#
# @lc app=leetcode id=2 lang=python3
#
# [2] Add Two Numbers
#

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


class Solution:
    def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
        num1 = ""
        num2 = ""
        while l1:
            num1 += str(l1.val)
            l1 = l1.next
        while l2:
            num2 += str(l2.val)
            l2 = l2.next
        res = str(int(num1[::-1]) + int(num2[::-1]))[::-1]
        head = ListNode(res[0])
        answer = head
        for i in res[1:]:
            node = ListNode(i)
            head.next = node
            head = head.next
        return answer

3. Longest Substring Without Repeating Characters

思路:用一个stack来存储不重复的元素,如果遇到没有见过的直接添加进去,如果遇到了就把之前的删除掉,重新把这个加载进来。

#
# @lc app=leetcode id=3 lang=python3
#
# [3] Longest Substring Without Repeating Characters
#
class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        stack = []
        max_len = 0 
        for index, item in enumerate(s):
            if item not in stack:
                stack.append(item)
                max_len = max(max_len , len(stack))
            else:
                idx = stack.index(item)
                stack = stack[idx+1:]
                stack.append(item)
                max_len = max(max_len,len(stack))
        return max_len

4 Median of Two Sorted Arrays

思路:这道题本质是一道二分搜索的题目。因为这两个是有序数组,同时时间复杂度要求。取出整个数列的中值,本质就是从两个数组中分别取出和个元素,同时,所以关键是要在两个数组中找到分割点,假设从A中选择了个数,从B中选择如果这时候是小于说明从A中选择的数目偏少,需要增加选择的数量如果小于表示从A中选择的数据太多,需要减少选择的数量。

image.png

image.png

class Solution:
    def findMedianSortedArrays(self, nums1, nums2):

        if len(nums1) > len(nums2):
            nums1, nums2 = nums2, nums1 
        m,n = len(nums1), len(nums2)
        left_size = (m+n+1) // 2 
        start = 0 
        end = m 
        is_even = ((m+n) %2) == 0 
        while start <= end:
            a_part = (start + end) // 2
            b_part = left_size - a_part

            aleftmax = float("-inf") if a_part == 0 else nums1[a_part - 1]
            arightmin = float("inf") if a_part == m else nums1[a_part]
            bleftmax = float("-inf") if b_part == 0 else nums2[b_part - 1]
            brightmin = float("inf") if b_part == n else nums2[b_part]

            if aleftmax <= brightmin and bleftmax <= arightmin:
                if not is_even:
                    return max(aleftmax, bleftmax)
                else:
                    return (max(aleftmax, bleftmax) + min(arightmin, brightmin)) / 2
            elif aleftmax > brightmin:
                end = a_part - 1
            elif bleftmax > arightmin:
                start = a_part + 1

if __name__ == '__main__':
    nums1, nums2 = [1, 3], [3, 4]
    solu = Solution()
    print(solu.findMedianSortedArrays(nums1, nums2))

5 Longest Palindromic Substring

思路:重复利用已经计算出来的回文子串,考虑 “ababa” 这个示例。如果我们已经知道 “bab” 是回文,那么很明显,“ababa” 一定是回文,因为它的左首字母和右尾字母是相同的。首先考虑两个类型一种是奇数回文,另外一种是偶数回文。
这产生了一个直观的动态规划解法,我们首先初始化一字母和二字母的回文,然后找到所有三字母回文

#

# @lc code=start
class Solution:
    def longestPalindrome(self, s: str) -> str:
        n = len(s)
        maxl, start = 0, 0 
        for i in range(n):
            if i-maxl >= 1 and s[i-maxl-1:i+1] == s[i-maxl-1:i+1][::-1]:
                start = i - maxl - 1 
                maxl += 2 
                continue
            if i - maxl >= 0 and s[i-maxl:i+1] == s[i-maxl:i+1][::-1]:
                start = i - maxl 
                maxl += 1 
        return s[start: start+maxl]

6 ZigZag Conversion

思路:增加一个标志位判断是向上走还是向下走,通过取余操作实现标志位的取值,初始值应该设为-1,因为程序在开始时就会命中换符号的逻辑。

# @lc app=leetcode id=6 lang=python3
#
# [6] ZigZag Conversion
#

# @lc code=start
class Solution:
    def convert(self, s: str, numRows: int) -> str:
        if numRows <= 1 or numRows > len(s):
            return s 
        res = [""] * numRows
        line, step = 0, -1
        for c in s:
            res[line] += c 
            if (line) % (numRows-1) == 0:
                step = -step 
            line += step 
        return "".join(res)

7 Reverse Integer

思路:没啥好说的,python切片就可以搞定,唯一需要考虑的就是越界问题

# [7] Reverse Integer
#

# @lc code=start
class Solution:
    def reverse(self, x: int) -> int:
        x = int(str(x)[::-1]) if x >= 0 else - int(str(-x)[::-1])
        return x if x < 2**31 and x >= -2**31 else 0

8 String to Integer (atoi)

思路:处理多种特殊情况

#
# @lc app=leetcode id=8 lang=python3
#
# [8] String to Integer (atoi)
#

# @lc code=start
class Solution:
    def myAtoi(self, s):
        """
        :type str: str
        :rtype: int
        """
        
        if len(s) == 0:
            return 0
        ls = list(s.strip())
        if len(ls) == 0:
            return 0


        sign = -1 if ls[0] == '-' else 1
        if ls[0] in ['-', '+']:
            del ls[0]
        ret, i = 0, 0
        while i < len(ls) and ls[i].isdigit():
            ret = ret*10 + ord(ls[i]) - ord('0')
            i += 1
        return max(-2**31, min(sign * ret, 2**31-1))

9 Palindrome Number

思路负数肯定不是回文数,之后再对正数和0进行判断

#
# @lc app=leetcode id=9 lang=python3
#
# [9] Palindrome Number
#

# @lc code=start
class Solution:
    def isPalindrome(self, x: int) -> bool:
        if x < 0:
            return False 
        else:
            if str(x) == str(x)[::-1]:
                return True 
            else:
                return False 

10 Regular Expression Matching

思路:动态规划令 dp[i][j] 为string s 前i位是否匹配p的前j位,为bool类型,例如dp[1][1]为s[0]、p[0]是否匹配,初始化后剩下的判断分为以下几种情况分析:

  1. p[j] == s[i] 或者 p[j] == '.' #匹配成功跟前面匹配一致
    dp[i+1][j+1] = dp[i][j]
  2. p[j] == '*' 这时又分两种情况
    (1)p[j-1] != s[i] #前的字符匹配0次
    dp[i+1][j+1] = dp[i+1][j-1]
    (2) p[j-1] == s[i] or p[j-1] != '.'
    dp[i+1][j+1] = dp[i][j+1] #该字符出现多次
    or dp[i+1][j+1] = dp[i+1][j] # 字符只出现一次
    or dp[i+1][j+1] = dp[i+1][j-1] # 字符匹配0次
class Solution:
    # @return a boolean
    def isMatch(self, s, pattern):
        dp = [[False] * (len(pattern)+1) for _ in range(len(s)+1)]
        dp[0][0] = True
        for i in range(len(pattern)):
            if pattern[i] == '*' and dp[0][i-1]:
                dp[0][i+1] = True
        for i in range(len(s)):
            for j in range(len(pattern)):
                if pattern[j] == s[i] or pattern[j] == '.':
                    dp[i+1][j+1] = dp[i][j]
                if pattern[j] == '*':
                    if pattern[j-1] != s[i] and pattern[j-1] != '.':
                        dp[i+1][j+1] = dp[i+1][j-1]
                    else:
                        dp[i+1][j+1] = (dp[i][j+1] or dp[i+1]
                                        [j] or dp[i+1][j-1])
        return dp[len(s)][len(pattern)]

你可能感兴趣的:(leetcode系列1 1-10)