用AI做算法题1

文章目录

1、python 求解两个数组nums1 nums2的交集

在Python中,你可以使用多种方法来求解两个数组(nums1 和 nums2)的交集。下面是几种常见的方法:

方法1:使用集合(Set)

集合是一个无序且不重复的元素集,它非常适合用于求解交集这样的操作。

python
Copy Code

def intersection(nums1, nums2):
    # 将两个列表转换为集合
    set1 = set(nums1)
    set2 = set(nums2)
    
    # 使用集合的交集操作
    return list(set1 & set2)

# 示例
nums1 = [1, 2, 2, 1]
nums2 = [2, 2]
print(intersection(nums1, nums2))  # 输出: 

方法2:使用列表推导式和集合

如果你不想显式地创建集合,也可以使用列表推导式和集合来求解交集。

python
Copy Code

def intersection(nums1, nums2):
    # 使用列表推导式和集合来求解交集
    return list(set([num for num in nums1 if num in nums2]))

# 示例
nums1 = [1, 2, 2, 1]
nums2 = [2, 2]
print(intersection(nums1, nums2))  # 输出: 

方法3:使用collections.Counter

collections.Counter 可以用来计算每个元素出现的次数,然后你可以通过比较两个计数器来找出交集。

python
Copy Code

from collections import Counter

def intersection(nums1, nums2):
    # 计算两个列表的元素频率
    counter1 = Counter(nums1)
    counter2 = Counter(nums2)
    
    # 找出两个计数器的公共键,并取最小的频率值
    common = {
   
   key: min(counter1[key], counter2[key]) for key in counter1 if key in counter2}
    
    # 将字典转换回列表
    return [item for item, count in common.items() for _ in range(count)]

# 示例
nums1 = [1, 2, 2, 1]
nums2 = [2, 2]
print(intersection(nums1, nums2))  # 输出: [2, 2]

注意,这种方法会保留交集中元素的出现次数。如果你只想要唯一的交集元素,可以像前面两种方法那样使用集合来去重。

方法4:使用itertools(仅适用于小数据集)

对于非常小的数据集,你也可以使用itertools库中的filterfalse函数结合匿名函数来求解交集。但这种方法通常不如前面的方法高效。

python
Copy Code

from itertools import filterfalse

def intersection(nums1, nums2):
    # 使用filterfalse和匿名函数来求解交集
    return list(filterfalse(lambda x: x not in nums2, nums1))

# 注意:这种方法不会去除重复元素,所以结果可能包含重复项
# 示例
nums1 = [1, 2, 2, 1]
nums2 = [2, 2]
print(intersection(nums1, nums2))  # 输出: [2, 2, 1, 2] (这不是期望的结果)

# 要去重,可以结合set使用
print(list(set(intersection(nums1, nums2))))  # 输出: [1, 2]

通常,方法1和方法2是最常用且最高效的,因为它们直接利用了集合的交集操作,而且代码简洁易懂。如果你需要保留交集中元素的出现次数,可以选择方法3。

2、给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树

在Java中,判断一个二叉树是否是有效的二叉搜索树(BST, Binary Search Tree),我们通常需要采用递归或迭代的方式遍历树,并在遍历的过程中验证每个节点是否满足BST的定义。一个有效的BST,对于每个节点,其左子树的所有节点值都必须小于该节点的值,而右子树的所有节点值都必须大于该节点的值。

为了实现这一点,我们可以定义一个辅助方法,该方法通过递归遍历树,并利用一个范围(由最小值和最大值构成)来检查每个节点是否满足条件。对于根节点,这个范围可以是负无穷大到正无穷大。随着我们深入树中,这个范围会根据当前节点的值进行更新。

以下是一个使用递归的Java实现,用于判断给定的二叉树是否是有效的二叉搜索树:

java
Copy Code

public class Solution {
   
   
    public boolean isValidBST(TreeNode root) {
   
   
        return isValidBSTHelper(root, Long.MIN_VALUE, Long.MAX_VALUE);
    }

    // 辅助方法,带有节点值范围的判断
    private boolean isValidBSTHelper(TreeNode node, long minVal, long maxVal) {
   
   
        // 空节点被视为有效的BST
        if (node == null) {
   
   
            return true;
        }

        // 如果节点的值不满足当前的范围,则不是BST
        if (node.val <= minVal || node.val >= maxVal) {
   
   
            return false;
        }

        // 递归检查左子树和右子树,注意要更新范围
        return isValidBSTHelper(node.left, minVal, node.val) &&
               isValidBSTHelper(node.right, node.val, maxVal);
    }

    // 树的节点定义
    public class TreeNode {
   
   
        int val;
        TreeNode left;
        TreeNode right;

        TreeNode(int x) {
   
   
            val = x;
        }
    }
}

在这个实现中,isValidBST方法是公开的接口,它调用了一个私有的辅助方法isValidBSTHelper。isValidBSTHelper方法接收当前节点以及该节点值的有效范围作为参数。如果当前节点为空,返回true(因为空树被视为有效的BST)。如果节点的值不在给定的范围内,返回false。否则,递归地检查左子树和右子树,同时更新范围:对于左子树,上界变为当前节点的值;对于右子树,下界变为当前节点的值。

请注意,这里使用了long类型来定义范围,以避免在节点值接近Integer.MAX_VALUE或Integer.MIN_VALUE时发生整数溢出。

class Solution {
   
   
    long pre = Long.MIN_VALUE;
    public boolean isValidBST(TreeNode root) {
   
   
        if (root == null) {
   
   
            return true;
        }
        // 访问左子树
        if (!isValidBST(root.left)) {
   
   
            return false;
        }
        // 访问当前节点:如果当前节点小于等于中序遍历的前一个节点,说明不满足BST,返回 false;否则继续遍历
        if (root.val <= pre) {
   
   
            return false;
        }
        pre = root.val;
        // 访问右子树
        return isValidBST(root.right);
    }
}

3、给你二叉树的根节点 root ,返回其节点值的 层序遍历 。

层序遍历(也称为广度优先搜索,BFS)是一种遍历二叉树的方法,它按照树的层级,从上到下、从左到右的顺序访问每个节点。在Java中,我们通常使用队列(Queue)来实现层序遍历,因为队列遵循先进先出的原则,这非常适合按层级处理节点。

下面是一个Java实现,用于返回二叉树节点值的层序遍历结果:

java
Copy Code
import java.util.*
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值