LeetCode[1]

整理一些思路,以便复盘记忆

1、两数之和

  • 题目:

给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。

你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。

示例:

给定 nums = [2, 7, 11, 15], target = 9

因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/two-sum

  • 我的解法:
    思路:直接遍历所有可能的两数组合,一旦发现与目标值相等,则返回索引;时间复杂度为 O ( n 2 ) O(n^2) O(n2)
class Solution(object):
    def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        N = len(nums)
        for i in range(N):
            for j in range(i+1,N,1):
                if nums[i]+nums[j] == target:
                    return [i,j]

在这里插入图片描述

  • 别人的解法:
    思路:采用hashmap求解,转化成通过键值获取索引;时间复杂度为 O ( n ) O(n) O(n)
class Solution(object):
    def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        hashmap = {}
        for i in range(len(nums)):
            if  target - nums[i] in hashmap.keys():
                return [hashmap[target - nums[i]],i]
            else:
                hashmap[nums[i]] = i

在这里插入图片描述时间上有较大改进

2、两数相加

  • 题目:

给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。

如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。

您可以假设除了数字 0 之外,这两个数都不会以 0 开头。

示例:

输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/add-two-numbers

  • 我的解法
    直接按照逻辑,一位一位相加、进位,时间复杂度为 O ( m a x ( m , n ) ) O(max(m,n)) O(max(m,n))
# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution(object):
    def addTwoNumbers(self, l1, l2):
        """
        :type l1: ListNode
        :type l2: ListNode
        :rtype: ListNode
        """
        a = l1
        b = l2
        c = ListNode(0)
        c_r = c         ##获取头节点
        up = 0
        while(1):
            temp = (a.val + b.val + up) % 10    ##获取个位
            up = int((a.val + b.val + up) / 10) ##获取进位
            c.val = temp
            if a.next == None and b.next == None and up == 0:   ##计算完毕
                break   
            elif a.next == None and b.next == None and up != 0: ##继续进行下一位计算
                a = ListNode(0)
                b = ListNode(0)
            elif a.next == None:
                a = ListNode(0)
                b = b.next
            elif b.next == None:
                b = ListNode(0)
                a = a.next
            else:
                b = b.next
                a = a.next
            c.next = ListNode(0)
            c = c.next
        return c_r
            

在这里插入图片描述- 别人的解法:
采用递归求解,想清楚输入输出是什么,以什么模式重复、终止条件是什么,时间复杂度为 O ( m a x ( m , n ) ) O(max(m,n)) O(max(m,n))

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

class Solution(object):
    def addTwoNumbers(self, l1, l2):
        """
        :type l1: ListNode
        :type l2: ListNode
        :rtype: ListNode
        """
        def add(a,b,carry=0):
            """
            a,b为当前加数和被加数
            carry为上一次的进位
            """
            if not (a or b):
                return ListNode(carry) if carry != 0 else None
            val = (a.val if a else 0) + (b.val if b else 0) + carry
            c, carry = ListNode(val%10), val//10 
            c.next = add(a.next if a else None,    ##若a已经是None,不存在a.next,则输入None
                         b.next if b else None,carry)
            return c
        return add(l1,l2,0)

在这里插入图片描述

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

  • 题目

给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

示例 1:

输入: “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。

示例 2:

输入: “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。

示例 3:

输入: “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters

  • 我的解法:
    依次遍历所有可能子串,计算不重复子串长度,时间复杂度 O ( n 2 ) O(n^2) O(n2)
class Solution(object):
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """
        N = len(s)
        l = []
        l_n = 0
        for j in range(N):
            if N-j < l_n:
                break
            for i in range(j,N,1):
                if s[i] not in l:
                    l.append(s[i])
                else:
                    if len(l) > l_n:
                        l_n = len(l)
                    l = []
                    break
        if len(l) > l_n:
            l_n = len(l)
        return l_n

在这里插入图片描述- 其他人的解法
滑动窗口方法,巧妙地将所有重复运算消除了,从左边开始,把字符一个一个放进来,一旦遇到重复出现的字符,就把该字符前面的所有字符都去掉(已经记录过之前的最长子串,所以不用担心去掉的字符),即把窗口左边的光标一下子移到重复字符的后面,右边的光标继续往右边走,时间复杂度 O ( n ) O(n) O(n)

跟刚才我的解法的区别在于:窗口左边的光标移动地更快了,右边窗口光标也不用回到左边

class Solution(object):
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """
        if len(s) == 0:
            return 0
        l = s[0]
        max_len = 1
        for i in range(1,len(s),1):
            if s[i] in l:              
                l = l[l.index(s[i])+1:]   # 删去重复字符前面的所有字符(已经记录过max length)
            l += s[i]
            if len(l) > max_len:
                max_len = len(l) 
        return max_len

在这里插入图片描述

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

  • 题目

给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。

请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。

你可以假设 nums1 和 nums2 不会同时为空。

示例 1:

nums1 = [1, 3]
nums2 = [2]

则中位数是 2.0

示例 2:

nums1 = [1, 2]
nums2 = [3, 4]

则中位数是 (2 + 3)/2 = 2.5

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/median-of-two-sorted-arrays

  • 我的解法
    堆条件堆逻辑,容易出错,大致思路是在nums1和nums2中从小到大一个一个找数字,直到找到的数字数量等于中位数所在的索引,时间复杂度大约为 O ( ( m + n ) / 2 ) O((m+n)/2) O((m+n)/2)
class Solution(object):
    def findMedianSortedArrays(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: float
        """
        N1 = len(nums1)
        N2 = len(nums2)
        t = int((N1+N2)/2)      ##中位数的索引位置1
        t0 = N1+N2-t*2          ##中位数的索引位置2
        ind1 = 0
        ind2 = 0
        c = 0               ##中位数的数值1
        c2 = 0             ##中位数的数值2
        if N1 == 0:
            if t0 != 0:
                return nums2[t]
            else:
                return float(nums2[t] + nums2[t-1]) / 2.0
        elif N2 == 0:
            if t0 != 0:
                return nums1[t]
            else:
                return float(nums1[t] + nums1[t-1]) / 2.0
        else:
            max0 = max([max(nums1),max(nums2)])
            for i in range(t+1):
                if N1 - ind1 < 1:
                    a = max0
                else:
                    a = (nums1[ind1])
                if N2 - ind2 < 1:
                    b = max0
                else:
                    b = (nums2[ind2])
                if a < b:               ## 在nums1,nums2中依次寻找从小到大的排列
                    if i == t-1:
                        c = a
                    elif i == t:
                        c2 = a
                    ind1 = ind1+1
                else:
                    if i == t-1:
                        c = b
                    elif i == t:
                        c2 = b
                    ind2 = ind2+1
            if t0 != 0:
                mid = c2
            else:
                mid = float(c+c2)/2.
            return mid

在这里插入图片描述

  • 别人的解法
    取i将nums1分成两部分,取j将nums2分成两部分,若i、j左边的最大值小于i、j右边的最小值,且i、j左边的数字数量满足中位数的要求,则可求得中位数
class Solution(object):
    def findMedianSortedArrays(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: float
        """
        m = len(nums1)
        n = len(nums2)
        if n > m:
            t = nums1
            nums1 = nums2
            nums2 = t
            m = n
            n = len(nums2)
        if n <= 1:
            for i in range(2-n):
                nums1.insert(0,-float('inf'))
                nums2.insert(len(nums2),float('inf'))
        m = len(nums1)
        n = len(nums2)
        mid_m = m/2
        i = mid_m
        while(1):
            j = (m+n)/2-i               # 将两个字符串看作整体,j随着i变
            if j == 0 or i == len(nums1):
                nums1.insert(len(nums1),float('inf'))
                nums2.insert(0,-float('inf'))
                i,m,n = i, m+1, n+1
                j = (m+n)/2-i
            if i == 0 or j == len(nums2):
                nums1.insert(0,-float('inf'))
                nums2.insert(len(nums2),float('inf'))
                i,m,n = i+1, m+1, n+1
                j = (m+n)/2-i
            a = nums1[i-1]
            b = nums2[j-1]
            if max([a,b]) <= min([nums1[i],nums2[j]]):    # 左边的最大值小于右边的最大值
                break
            elif b > min([nums1[i],nums2[j]]):
                i = i + 1
            else:
                i = i - 1
        
        if (m+n)%2==0:
            return (max([a,b]) + min([nums1[i],nums2[j]]))/2.0
        else:
            return min([nums1[i],nums2[j]])


在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值