数组(Array)是有序的元素序列。 若将有限个类型相同的变量的集合命名,那么这个名称为数组名。组成数组的各个变量称为数组的分量,也称为数组的元素,有时也称为下标变量。用于区分数组的各个元素的数字编号称为下标。数组是在程序设计中,为了处理方便, 把具有相同类型的若干元素按有序的形式组织起来的一种形式。 这些有序排列的同类数据元素的集合称为数组。
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
真题点击此处:1.两数之和
方法一:暴力解法
思路:通过两层循环来枚举数组中的每一个数字,并将他们相加,如果和为target,则返回答案。
以下为代码实现:
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
for i in range(len(nums)-1):
for j in range(i+1,len(nums)):
if nums[i]+nums[j]==target:
return [i,j]
return []
时间复杂度:由于我们嵌套了两层循环,所以时间复杂度为O(n2)
空间复杂度:O(1)
方法二:哈希表实现
思路:设哈希表为cnt,在一层循环中枚举到当前数字时nums[i]时,如果target-nums[i]在哈希表中,我们就返回当前的下标 i 和cnt[target-nums[i]]的值,否则将nums[i]添加到哈希表中。
以下为代码实现:
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
cnt=dict()
for i,num in enumerate(nums):
if target-num in cnt:
return[cnt[target-num],i]
cnt[num]=i
return []
时间复杂度:我们在这里只循环了一次,所以时间复杂度是O(n)
空间复杂度:我们使用一个哈希表来存储数据,所以空间复杂度为O(n)
给你一个 非空 整数数组 nums ,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。
真题点击此处:136.只出现一次的数字
方法一:哈希表
思路:我们通过将这个数组的值存储在一个哈希表中,通过循环判断每一个键的值,找出值为1的那个键即为只出现一次的数字
以下为代码实现:
class Solution:
def singleNumber(self, nums: List[int]) -> int:
cnt=Counter(nums)
for c in cnt:
if cnt[c]==1:
return c
时间复杂度:只用了一次循环,所以时间复杂度为O(n)
空间复杂度:用了一个哈希表来存储数据,所以空间复杂度为O(n)
方法二:异或
思路:我们首先要知道,一个数字与它本身进行异或的结果是为0的,如何3 ^ 3就是 11(二进制) ^ 11,根据异或的规律,相同为0,不同为1,所以3 ^ 3的结果为0,由题意可知,只有一个数字出现了一次,其他数字都出现了两次,因此我们就可以得出所有出现次数为2的数字最后的结果都可以异或为0。
以下为代码实现:
class Solution:
def singleNumber(self, nums: List[int]) -> int:
ans=0
for num in nums:
ans^=num
return ans
时间复杂度:同样的,一次循环,时间复杂度为O(n)
空间复杂度:只使用了常量的空间,空间复杂度为O(1)
给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。
请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。
注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。
真题点击此处:88.合并两个有序数组
方法一:直接合并排序
思路:直接将nums2的值加入到nums1中,然后进行排序
以下为代码实现:
class Solution:
def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
"""
Do not return anything, modify nums1 in-place instead.
"""
j=0
for i in range(m,m+n):
nums1[i]=nums2[j]
j+=1
nums1.sort()
return nums1
时间复杂度:套用快速排序的时间复杂度,平均复杂度为O((m+n)log(m+n))
空间复杂度:套用快速排序的空间复杂度,平均复杂度为O(log(m+n))
方法二:逆向双指针
思路:采用逆向双指针可以避免出现元素被覆盖的问题,因为在任一时刻总会出现一个位置被覆盖,另一个位置被空出的情况,因此不会出现覆盖问题。
以下为代码实现:
class Solution:
def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
"""
Do not return anything, modify nums1 in-place instead.
"""
while n>0:
if m>0 and nums1[m-1]>nums2[n-1]:
nums1[m+n-1]=nums1[m-1]
m-=1
else:
nums1[m+n-1]=nums2[n-1]
n-=1
return nums1
时间复杂度:指针移动向递减,最多移动m+n次,因此时间复杂度为O(m+n)
空间复杂度:直接对数组原地修改,因此空间复杂度为O(1)