从0开始刷算法题(leetcode数组篇)-- day01

数组--day01

    • 1. 数组概述
    • 2. 两数之和
    • 3.只出现一次的数字
    • 4. 合并两个有序数组

1. 数组概述

数组(Array)是有序的元素序列。 若将有限个类型相同的变量的集合命名,那么这个名称为数组名。组成数组的各个变量称为数组的分量,也称为数组的元素,有时也称为下标变量。用于区分数组的各个元素的数字编号称为下标。数组是在程序设计中,为了处理方便, 把具有相同类型的若干元素按有序的形式组织起来的一种形式。 这些有序排列的同类数据元素的集合称为数组。

2. 两数之和

给定一个整数数组 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)

3.只出现一次的数字

给你一个 非空 整数数组 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)

4. 合并两个有序数组

给你两个按 非递减顺序 排列的整数数组 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)

你可能感兴趣的:(算法学习,算法,leetcode)