LeetCodePractice-20210611
Posted Circle-C
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCodePractice-20210611相关的知识,希望对你有一定的参考价值。
剑指 Offer 03. 数组中重复的数字
找出数组中重复的数字。
在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
示例 1:
输入:
[2, 3, 1, 0, 2, 5, 3]
输出:2 或 3
限制:
2 <= n <= 100000
链接:https://leetcode-cn.com/problems/shu-zu-zhong-zhong-fu-de-shu-zi-lcof
Solution1
nums = [2, 3, 1, 0, 2, 5, 3]
ans = set([n for n in nums if nums.count(n) > 1])
ans
hashTable = [0] * 100000
for n in nums:
hashTable[n] += 1
if hashTable[n] > 1:
print(n)
break
剑指 Offer 04. 二维数组中的查找
在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个高效的函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
示例:
现有矩阵 matrix 如下:
[
[1, 4, 7, 11, 15],
[2, 5, 8, 12, 19],
[3, 6, 9, 16, 22],
[10, 13, 14, 17, 24],
[18, 21, 23, 26, 30]
]
给定 target = 5,返回 true。
给定 target = 20,返回 false。
限制:
0 <= n <= 1000
0 <= m <= 1000
链接:https://leetcode-cn.com/problems/er-wei-shu-zu-zhong-de-cha-zhao-lcof
matrix = [
[1, 4, 7, 11, 15],
[2, 5, 8, 12, 19],
[3, 6, 9, 16, 22],
[10, 13, 14, 17, 24],
[18, 21, 23, 26, 30]
]
matrix = [
[-5, 4, 7, 11, 15],
[2, 5, 8, 12, 19],
[3, 6, 9, 16, 22],
]
matrix = [[-5]]
matrix = [[]]
target = -5
target = -2
target = 5
target = 11
target = 8
target = 22
target = 25
Solution1
i = len(matrix) - 1
j = 0
while i >= 0 and j < len(matrix[0]):
if target > matrix[i][j]:
j += 1
elif target < matrix[i][j]:
i -= 1
else:
print(True)
break
print(False)
Solution2
[j for i in matrix for j in i]
target in [j for i in matrix for j in i]
bool([])
bool([[]])
剑指 Offer 06. 从尾到头打印链表
输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。
示例 1:
输入:head = [1,3,2]
输出:[2,3,1]
限制:
0 <= 链表长度 <= 10000
链接:https://leetcode-cn.com/problems/cong-wei-dao-tou-da-yin-lian-biao-lcof
Solution1-递归
from typing import List
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
class Solution:
def reversePrint(self, head: ListNode) -> List[int]:
if head != None:
return self.reversePrint(head.next) + [head.val]
else:
return []
head = ListNode(2)
head.next = ListNode(3)
Solution().reversePrint(head)
Solution2-Stack
class Solution2:
def reversePrint(self, head: ListNode) -> List[int]:
array = []
while head:
array.append(head.val)
head = head.next
return array[::-1]
Solution2().reversePrint(head)
剑指 Offer 10- I. 斐波那契数列
写一个函数,输入 n ,求斐波那契(Fibonacci)数列的第 n 项(即 F(N))。斐波那契数列的定义如下:
F(0) = 0, F(1) = 1
F(N) = F(N - 1) + F(N - 2), 其中 N > 1.
斐波那契数列由 0 和 1 开始,之后的斐波那契数就是由之前的两数相加而得出。
答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。
示例 1:
输入:n = 2
输出:1
示例 2:
输入:n = 5
输出:5
提示:
0 <= n <= 100
链接:https://leetcode-cn.com/problems/fei-bo-na-qi-shu-lie-lcof
class Solution:
def fib(self, n: int) -> int:
if n == 0:
return 0
if n == 1:
return 1
return self.fib(n - 1) + self.fib(n - 2)
Solution().fib(1)
0 1 1 2 3 5
class Solution2:
def fib(self, n: int) -> int:
if n == 0:
return 0
if n == 1:
return 1
a, b = 0, 1
for _ in range(n):
a, b = b, a + b
print(a)
return a
Solution2().fib(45)
53. 最大子序和
https://leetcode-cn.com/problems/maximum-subarray/
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
示例 1:
输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6
解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。
示例 2:
输入:nums = [1]
输出:1
示例 3:
输入:nums = [0]
输出:0
示例 4:
输入:nums = [-1]
输出:-1
示例 5:
输入:nums = [-100000]
输出:-100000
提示:
1 <= nums.length <= 3 * 104
-105 <= nums[i] <= 105
进阶:如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的 分治法 求解。
通过次数526,186提交次数969,361
链接:https://leetcode-cn.com/problems/maximum-subarray
nums = [-2,1,-3,4,-1,2,1,-5,4]
方法一:贪心
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b8ozfbgV-1623416063944)(images\\最大子序列和-贪心.png)]
- 时间复杂度: O(N),只遍历一次数组
- 空间复杂度: O(1),只使用了常数空间
def maxSubArray(nums):
if not nums: return -214783648
cur_sum = max_sum = nums[0]
for i in range(1, len(nums)):
cur_sum = max(nums[i], cur_sum + nums[i])
max_sum = max(cur_sum, max_sum)
return max_sum
maxSubArray(nums)
方法二:动态规划
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xegLYlSC-1623416063950)(images\\最大子序列和-动态规划.png)]
def maxSubArray(nums):
if not nums: return -214783648
for i in range(1, len(nums)):
if nums[i-1] > 0:
nums[i] = nums[i-1] + nums[i]
max_sum = max(nums)
return max_sum
maxSubArray(nums)
1282. 用户分组
有 n 位用户参加活动,他们的 ID 从 0 到 n - 1,每位用户都 恰好 属于某一用户组。给你一个长度为 n 的数组 groupSizes,其中包含每位用户所处的用户组的大小,请你返回用户分组情况(存在的用户组以及每个组中用户的 ID)。
你可以任何顺序返回解决方案,ID 的顺序也不受限制。此外,题目给出的数据保证至少存在一种解决方案。
示例 1:
输入:groupSizes = [3,3,3,3,3,1,3]
输出:[[5],[0,1,2],[3,4,6]]
解释:
其他可能的解决方案有 [[2,1,6],[5],[0,4,3]] 和 [[5],[0,6,2],[4,3,1]]。
示例 2:
输入:groupSizes = [2,1,3,3,3,2]
输出:[[1],[0,5],[2,3,4]]
提示:
groupSizes.length == n
1 <= n <= 500
1 <= groupSizes[i] <= n
链接:https://leetcode-cn.com/problems/group-the-people-given-the-group-size-they-belong-to
groupSizes = [3,3,3,3,3,1,3]
groupSizes = [2,1,3,3,3,2]
def groupThePeople(groupSizes):
group_index = 0
ans = [[]]
d = {}
for i, size in enumerate(groupSizes):
if size not in d.keys():
d[size] = [i]
else:
if
d[size].append(i)
def groupThePeople(groupSizes):
ans = [] # 存放各组的用户下标
group_index = {} # 记录用户组ans所在的下标
index = 0 # 组的个数(下标)
# 从头遍历每个元素
for i, size in enumerate(groupSizes):
# print(size, group_index, ans)
# 如果用户组大小没有记录,则新建一组,将其下标存到该组
if size not in group_index.keys():
group_index[size] = index
ans.append([])
ans[group_index[size]].append(i)
index += 1
# 如果用户组大小有记录
else:
# 且该组用户没有满
if len(ans[group_index[size]]) < size:
ans[group_index[size]].append(i)
# 且该组用户已满
else:
# 新建一组
group_index[size] = index
ans.append([])
ans[group_index[size]].append(i)
index += 1
return ans
groupThePeople(groupSizes)
1. 两数之和
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
示例 1:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
示例 2:
输入:nums = [3,2,4], target = 6
输出:[1,2]
示例 3:
输入:nums = [3,3], target = 6
输出:[0,1]
提示:
2 <= nums.length <= 104
-109 <= nums[i] <= 109
-109 <= target <= 109
只会存在一个有效答案
进阶:你可以想出一个时间复杂度小于 O(n2) 的算法吗?
链接:https://leetcode-cn.com/problems/two-sum
nums = [2,7,11,15]
target = 9
nums = [3,2,4]
target = 6
nums = [3,3]
target = 6
方法一:暴力求解
def twoSum(nums, target):
for i, e1 in enumerate(nums):
for j, e2 in enumerate(nums[i+1:]):
if e1 + e2 == target:
return [i, i+j+1]
twoSum(nums, target)
方法二:查找表法
思路及算法
注意到方法一的时间复杂度较高的原因是寻找 target - x 的时间复杂度过高。因此,我们需要一种更优秀的方法,能够快速寻找数组中是否存在目标元素。如果存在,我们需要找出它的索引。
使用哈希表,可以将寻找 target - x 的时间复杂度降低到从 O(N)O(N) 降低到 O(1)O(1)。
这样我们创建一个哈希表,对于每一个 x,我们首先查询哈希表中是否存在 target - x,然后将 x 插入到哈希表中,即可保证不会让 x 和自己匹配。
复杂度分析
时间复杂度:O(N)O(N),其中 NN 是数组中的元素数量。对于每一个元素 x,我们可以 O(1)O(1) 地寻找 target - x。
空间复杂度:O(N)O(N),其中 NN 是数组中的元素数量。主要为哈希表的开销。
def twoSum(nums, target):
hashTable = {}
for i, e in enumerate(nums):
if target - e not in hashTable.keys():
hashTable[e] = i
else:
return [hashTable[target - e], i]
twoSum(nums, target)
15. 三数之和
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例 1:
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
示例 2:
输入:nums = []
输出:[]
示例 3:
输入:nums = [0]
输出:[]
提示:
0 <= nums.length <= 3000
-105 <= nums[i] <= 105
链接:https://leetcode-cn.com/problems/3sum
nums = [-1,0,1,2,-1,-4]
nums = [0,0,0,0]
nums = [-2,0,1,1,2]
双指针法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9hX8tBjE-1623416063952)(images\\三数之和.png)]
拿这个nums数组来举例,首先将数组排序,然后有一层for循环,i从下表0的地方开始,同时定一个下表left 定义在i+1的位置上,定义下表right 在数组结尾的位置上。
依然还是在数组中找到 abc 使得a + b +c =0,我们这里相当于 a = nums[i] b = nums[left] c = nums[right]。
接下来如何移动left 和right呢, 如果nums[i] + nums[left] + nums[right] > 0 就说明 此时三数之和大了,因为数组是排序后了,所以right下表就应该向左移动,这样才能让三数之和小一些。
如果 nums[i] + nums[left] + nums[right] < 0 说明 此时 三数之和小了,left 就向右移动,才能让三数之和大一些,直到left与right相遇为止。
时间复杂度:O(n^2)。
def threeSum(nums):
nums = sorted(nums)
ans = []
for i, e1 in enumerate(nums):
left = i+1
right = len(nums) - 1
while left < right:
e2 = nums[left]
e3 = nums[right]
s = e1 + e2 + e3
if s == 0:
if [e1, e2, e3] not in ans:
ans.append([e1, e2, e3])
left += 1
elif s < 0:
left += 1
else:
right -= 1
return ans
threeSum(nums)
3. 无重复字符的最长子串
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2:
输入: s = “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3:
输入: s = “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。
示例 4:
输入: s = “”
输出: 0
提示:
0 <= s.length <= 5 * 104
s 由英文字母、数字、符号和空格组成
链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters
s = "abcabcbb"
s = "bbbbb"
s = "pwwkew"
s = ''
s = ' '
s = "dvdf"
ans = 0
substr = ''
substr_len = 0
if s == '': ans = 0
for i in s:
if i not in substr:
substr_len += 1
substr += i
else:
substr = substr[substr.index(i)+1:] + i
substr_len = len(substr)
if substr_len > ans: ans = substr_len
ans
48. 旋转图像
给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。
你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。
示例 1:
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[[7,4,1],[8,5,2],[9,6,3]]
示例 2:
输入:matrix = [[5,1,9,11],[2,4,8,10],[13,3,6,7],[15,14,12,16]]
输出:[[15,13,2,5],[14,3,4,1],[12,6,8,9],[16,7,10,11]]
示例 3:
输入:matrix = [[1]]
输出:[[1]]
示例 4:
输入:matrix = [[1,2],[3,4]]
输出:[[3,1],[4,2]]
提示:
matrix.length == n
matrix[i].length == n
1 <= n <= 20
-1000 <= matrix[i][j] <= 1000
链接:https://leetcode-cn.com/problems/rotate-image
matrix = [[1,2,3],[4,5,6],[7,8,9]]
length = len(matrix)
for i in range(length):
for j in range(length):
if j < i:
temp = matrix[i][j]
matrix[i][j] = matrix[j][i]
matrix[j][i] = temp
matrix
for i in range(length):
for j in range(length//2):
temp = matrix[i][length - j -1]
matrix[i][length - j -1] = matrix[i][j]
matrix[i][j] = temp
matrix
279. 完全平方数
给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, …)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。
给你一个整数 n ,返回和为 n 的完全平方数的 最少数量 。
完全平方数 是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。例如,1、4、9 和 16 都是完全平方数,而 3 和 11 不是。
示例 1:
输入:n = 12
输出:3
解释:12 = 4 + 4 + 4
示例 2:
输入:n = 13
输出:2
解释:13 = 4 + 9
提示:
1 <= n <= 104
链接:https://leetcode-cn.com/problems/perfect-squares
import math
n 以上是关于LeetCodePractice-20210611的主要内容,如果未能解决你的问题,请参考以下文章