找出不是两个数组共有的元素_06.数组(练习篇)

title: LeetCode 第 15 号问题:三数之和(中等)

date: '2020-5-23'

updated: '2020-5-25'

tags: [LeetCode]

题目:

# 给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复
# 的三元组。
#
#  注意:答案中不可以包含重复的三元组。
#
#
#
#  示例:
#
#  给定数组 nums = [-1, 0, 1, 2, -1, -4],
#
# 满足要求的三元组集合为:
# [
#   [-1, 0, 1],
#   [-1, -1, 2]
# ]

题目解析

题目需要我们找出三个数且和为 0 ,那么除了三个数全是 0 的情况之外,肯定会有负数和正数,所以一开始可以先选择一个数,然后再去找另外两个数,这样只要找到两个数且和为第一个选择的数的相反数就行了。也就是说需要枚举 a 和 b ,将 c 的存入 map 即可。

需要注意的是返回的结果中,不能有有重复的结果。这样的代码时间复杂度是 O(n^2)。在这里可以先将原数组进行排序,然后再遍历排序后的数组,这样就可以使用双指针以线性时间复杂度来遍历所有满足题意的两个数组合。

动画描述

待更新

代码实现

方法一:暴力破解法:三层for循环

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        res = []
        nums.sort()  # 对列表进行排序,方便后面的循环操作
        for i in range(len(nums) - 2): # 找出第一个数
            for j in range(i+1, len(nums) - 1):  # 第二个数
                for k in range(j + 1, len(nums)):  # 第三个数
                    if nums[k] + nums[i] + nums[j] == 0 and [nums[i], nums[j], nums[k]] not in res:
                          # 使用not in res 会加大时间复杂度
                        res.append([nums[i],nums[j], nums[k]])
        return re

运行结果:

b2078c91de82c0854e1c11d448209c46.png

由于时间复杂度为O(n^4),所以运行超时。

方法二:指针+排序

解法分析:

1.双指针法铺垫:先将给定nums排序,复杂度为O(NlogN)O(NlogN)。

2.双指针法思路: 固定3 个指针中最左(最小)数字的指针 k,双指针 i,j 分设在数组索引 (k, len(nums))(k,len(nums)) 两端,通过双指针交替向中间移动,记录对于每个固定指针 k 的所有满足 -- nums[k] = nums[i] + nums[j] 的 i,j 组合:

  • 分三种情况进行讨论:
    • 1.num[k] > 0 时退出程序
    • 2.--num[k] < nums[i] + nums[j] 此时i往左移,即 i += 1
    • 3.--num[k] > nums[i] + nums[j] 此时i往左移,即 j -= 1
class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:        
        nums.sort()#对数组进行排序
        res,k=[],0 #res用来返回新的列表
        for k in range(len(nums)-2):
        #由于第一个数只有是负数才能够正常进行
            if nums[k] > 0:
                break
             # 引入三个指针,将对k指针尽心讨论
            if k > 0 and num[k] == nums[k - 1]:  # 对k值是否相等进行讨论
                continue
            i, j = k+1, len(nums) - 1  # i,j 两个指针从下标为1和下标为last开始移动
            while i<j:
                s = nums[k] + nums[i] + nums[j]
                if s < 0:  #当s<0的话,说明此时的值还是太小,需要往大的数进行移动
                    i +=1  # 在运行完成之后还要考虑i是不是在
                elif s > 0:
                    j -= 1  # 同上
                else:
                    res.append((nums[k],nums[i],nums[j]))
                    #对新的列表进行更新
                 # 解决上面的问题:出现多个i 和 j 怎么处理, 当
                    while i<j and nums[i] == nums[i+1]:
                        i+=1
                    while i<j and nums[j] == nums[j-1]:
                       j-=1
                    i += 1;j -= 1
        return res

运行结果

86ef71e1abf9171efd86ce357118e6c1.png

复杂度分析:

  • 时间复杂度 O(N^2):其中固定指针k循环复杂度 O(N),双指针 i,j 复杂度 O(N)
  • 空间复杂度 O(1):指针使用常数大小的额外空间。

方法三:哈希表解法

待更新


title: LeetCode 第 283 号问题:零移动(简单)

date: '2020-5-24'

updated: '2020-5-25'

tags: [LeetCode]

题目:

# 给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
#
#  示例:
#
#  输入: [0,1,0,3,12]
# 输出: [1,3,12,0,0]
#
#  说明:
#
#
#  必须在原数组上操作,不能拷贝额外的数组。
#  尽量减少操作次数。
#
#  Related Topics 数组 双指针

题目分析:

设定一个临时变量 k = 0,遍历数组 nums ,将非零元素移动到 nums[k]位 置,同时 k++,而后将[k,….nums.size()]中的元素置零。

方法一:暴力破解法

class Solution:
    def moveZeroes(self, nums: List[int]) -> None:
        """
        遍历 nums ,将 nums 中为0的使用append方法添加到列表后,再紧接着把0移出列表
        Do not return anything, modify nums in-place instead.
        """
        # 暴力破解法
        for i in nums[:]:
            if i == 0:
                nums.append(0)
                nums.remove(0)

                 

时间复杂度分析:

由于使用for循环,所以时间复杂度为O(n)

方法二:指针法

解析方法:

1.首先定义两个指针分别为 i,j

2.使用在指针中常用的夹击法,一个i指针从下标为0的位置出发,j指针从下标为last进行移动

3.j指针是用来将数字0移动到last,并且i 和 j 的元素交换位置1就可以实现,在python中交换两个数的值是比较简单的。

动画描述:

256d3f1f4222f8afb75eb3dffc25b923.gif
#方法二:进行值的交换

class Solution:
    def moveZeroes(self, nums: List[int]) -> None:
        i = 0
        j = len(nums)
        for i in range(len(nums)):
            if nums[i] != 0:
                nums[i],nums[j] = nums[j],nums[i]
                j -= 1

时间复杂度分析:时间复杂度为O(n),空间复杂度O(1)

总结:解决此类问题:一般采用双指针法和用栈进行维护

### 回答1: 这道题要求找出不是两个数组共有元素。 具体做法是,先将两个数组合并成一个新的数组,然后遍历新数组中的每个元素,判断它是否同时存在于原来的两个数组中,如果不是,则将其加入到结果数组中。 最后返回结果数组即可。 代码示例: ```python def find_different_elements(arr1, arr2): # 将两个数组合并成一个新数组 new_arr = arr1 + arr2 # 初始化结果数组 result = [] # 遍历新数组中的每个元素 for elem in new_arr: # 判断该元素是否同时存在于原来的两个数组中 if elem not in arr1 or elem not in arr2: # 如果不是,则将其加入到结果数组中 result.append(elem) # 返回结果数组 return result ``` 注意,上述代码中的 `not in` 表示不在数组中,即表示该元素不属于该数组。 ### 回答2: 练习7-4要求我们编写一个程序,在两个给定的数组中,找出不是共有元素元素,并输出它们。 首先,我们需要输入这两个数组。可以使用以下代码: ```python A = list(map(int, input().split())) B = list(map(int, input().split())) ``` 接着,我们可以使用set和&运算符来找出两个数组共有元素。代码如下: ```python set_A = set(A) set_B = set(B) common = set_A & set_B ``` 然后,我们可以使用列表推导式来找出不是共有元素元素。代码如下: ```python not_common = [x for x in A + B if x not in common] ``` 其中,A+B将A和B拼接成一个新的列表,而列表推导式的if语句用来判断x是否在common中出现过。 最后,我们可以使用以下代码将结果输出: ```python for x in not_common: print(x, end=' ') ``` 完整代码如下: ```python A = list(map(int, input().split())) B = list(map(int, input().split())) set_A = set(A) set_B = set(B) common = set_A & set_B not_common = [x for x in A + B if x not in common] for x in not_common: print(x, end=' ') ``` 以上就是练习7-4的解答。 ### 回答3: 这道题要求找出两个数组中不共有元素,首先我们需要先了解什么是两个数组共有元素两个数组共有元素就是两个数组都拥有的元素,比如数组A有{1,2,3,4},数组B有{3,4,5,6},那么两个数组共有元素就是3和4。 那么我们需要找出的就是两个数组中没有共有元素。我们可以通过遍历两个数组来实现这个目的。对于数组A中的每一个元素,我们都需要在数组B中查找是否存在相同的元素。如果存在,则说明这是两个数组共有元素,否则这个元素就是数组A特有的元素。 同样地,我们也需要遍历数组B中的每一个元素,在数组A中查找是否存在相同的元素,如果不存在,则说明这是数组B特有的元素。 最后我们将两个数组特有的元素合并在一起,即为题目所求答案。下面是Python代码实现: ```python def unique_elements(arr1, arr2): unique = [] for num in arr1: if num not in arr2: unique.append(num) for num in arr2: if num not in arr1: unique.append(num) return unique ``` 在上述代码中,我们定义了一个名为 unique_elements 的函数,该函数接受两个数组 arr1 和 arr2 作为参数,返回两个数组中特有的元素组成的新数组 unique。 在函数内部,我们使用了两个 for 循环遍历两个数组,并通过 if 语句判断数组中的元素是否在另一个数组中存在,如果不存在,则将其加入到 unique 数组中。 最后,我们返回 unique 数组,即为所求答案。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值