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]])