华为OD 2023机试题java python c++ go rust

本文涉及的产品
Serverless 应用引擎 SAE,800核*时 1600GiB*时
云原生网关 MSE Higress,422元/月
可观测可视化 Grafana 版,10个用户账号 1个月
简介: 华为OD 2023机试题java python c++ go rust

给定一个字符串 s ,找出这样一个子串:

1)该子串中的任意一个字符最多出现2次;

2)该子串不包含指定某个字符;

请你找出满足该条件的最长子串的长度。

输入描述:第一行为要求不包含的指定字符,为单个字符,取值范围0-9a-zA-Z

第二行为字符串s,每个字符范围0-9a-zA-Z,长度范围1,10000

输出描述:一个整数,满足条件的最长子串的长度;如果不存在满足条件的子串,则返回0

示例

示例1

输入:

D

ABC123

输出:6

示例2

输入:

D

ABACA123D

输出:7

解题思路

我们定义left和right两个指针,左右指针代表当前考察的子串的左右边界。

在移动右指针时,如果新加入的字符没有出现过,或者出现次数没有超过2次,我们就扩大窗口,并更新最大长度。

如果新加入的字符已经出现过2次,我们就收缩窗口的左侧边界,直到移除了一个重复出现的字符。

我们重复这个过程,直到right指针遍历完整个字符串,就可以得到满足条件的最长子串长度。

时间复杂度:O(n)O(n),n为字符串长度。

空间复杂度:O(1)O(1)。

Java实现

import java.util.HashSet;
import java.util.Set;
public class LongestSubstring {
    public int lengthOfLongestSubstring(String s, char excluded) {
        Set<Character> set = new HashSet<>();
        int left = 0, right = 0;
        int max = 0;
        while (right < s.length()) {
            if (set.add(s.charAt(right))) {
                max = Math.max(max, right - left + 1);
                right++;
            } else {
                set.remove(s.charAt(left++));
            }
        }
        return max;
    }
    public static void main(String[] args) {
        LongestSubstring solution = new LongestSubstring();
        String s = "ABC123";
        char c = 'D';
        System.out.println(solution.lengthOfLongestSubstring(s, c));
    }
}

python

class LongestSubstring:
    def lengthOfLongestSubstring(self, s, excluded):
        s = list(s)
        set = set() # 创建一个空集合
        left = 0 # 初始化左指针
        right = 0 # 初始化右指针
        max = 0 # 初始化最大子串长度
        while right < len(s):
            if s[right] not in set: # 如果当前字符不在集合中
                set.add(s[right]) # 将当前字符加入集合
                max = max(max, right - left + 1) # 更新最大子串长度
                right += 1 # 右指针右移
            else:
                set.remove(s[left]) # 将左指针指向的字符从集合中移除
                left += 1 # 左指针右移
        return max # 返回最大子串长度

solution = LongestSubstring()
s = "ABC123"
c = 'D'
print(solution.lengthOfLongestSubstring(s, c)) # 输出最大子串长度

C++

#include <iostream>
#include <unordered_set>
using namespace std;

class LongestSubstring {
public:
    int lengthOfLongestSubstring(string s, char excluded) {
        unordered_set<char> set; // 创建一个无序集合
        int left = 0, right = 0; // 初始化左右指针
        int max = 0; // 初始化最大长度
        while (right < s.length()) { // 当右指针小于字符串长度时
            if (set.insert(s[right]).second) { // 如果插入成功
                max = std::max(max, right - left + 1); // 更新最大长度
                right++; // 右指针右移
            } else { // 如果插入失败
                set.erase(s[left++]); // 左指针右移
            }
        }
        return max; // 返回最大长度
    }
};

int main() {
    LongestSubstring solution; // 创建一个 LongestSubstring 类的实例
    string s = "ABC123"; // 初始化字符串
    char c = 'D'; // 初始化排除字符
    cout << solution.lengthOfLongestSubstring(s, c) << endl; // 输出最大长度
    return 0;
}

go

// 将给定字符串s转换为字符数组
s := []rune(s)

// 创建一个空map,用于存储字符出现的位置
set := make(map[rune]int)

// 初始化左指针和最大子串长度
left, max := 0, 0

// 遍历字符串
for right, char := range s {
    // 如果字符已经在map中出现过,并且出现位置在左指针右侧
    if _, ok := set[char]; ok && set[char] >= left {
        // 将左指针移动到该字符出现位置的右侧
        left = set[char] + 1
    }
    // 更新最大子串长度
    max = int(math.Max(float64(max), float64(right-left+1)))
    // 将字符出现位置存入map中
    set[char] = right
}

// 返回最大子串长度
return max

rust

// 将给定字符串s转换为字符数组
let s: Vec<char> = s.chars().collect();

// 创建一个空map,用于存储字符出现的位置
let mut set: HashMap<char, usize> = HashMap::new();

// 初始化左指针和最大子串长度
let (mut left, mut max) = (0, 0);

// 遍历字符串
for right in 0..s.len() {
    let char = s[right];
    // 如果字符已经在map中出现过,并且出现位置在左指针右侧
    if let Some(&pos) = set.get(&char) {
        if pos >= left {
            // 将左指针移动到该字符出现位置的右侧
            left = pos + 1;
        }
    }
    // 更新最大子串长度
    max = max.max(right - left + 1);
    // 将字符出现位置存入map中
    set.insert(char, right);
}

// 返回最大子串长度
max
  1. 实现一个函数,判断一棵二叉树是否对称。例如:下面这棵树是对称的。    
 1

   /  \

  2    2

 / \  / \

3  4 4  3

伪代码思路

定义一个函数判断二叉树是否对称,需要传入根节点和父节点。

如果当前节点是左子树的根节点,则递归判断右子树是否对称。

如果当前节点是右子树的根节点,则递归判断左子树是否对称。

如果左右子树都不对称,则返回false。

如果左右子树都对称,则返回true。

在主函数中调用该函数,传入根节点和父节点进行测试。

java

class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x) { val = x; }
}

public boolean isSymmetric(TreeNode root) {
    if (root == null) return true;
    return check(root.left, root.right) && isSymmetric(root.left) && isSymmetric(root.right);
}

private boolean check(TreeNode left, TreeNode right) {
    if (left == null && right == null) return true; // 如果左右子树都为空,则对称
    if (left == null || right == null) return false; // 如果左右子树有一个为空,则不对称
    if (left.val != right.val) return false; // 如果左右子树的值不相等,则不对称
    return check(left.left, right.right) && check(left.right, right.left); // 分别递归检查左右子树是否对称
}

public static void main(String[] args) {
        // 创建一棵二叉树并测试对称性
        TreeNode root = new TreeNode(1);
        root.left = new TreeNode(2);
        root.right = new TreeNode(2);
        root.right.left = new TreeNode(3);
        root.right.right = new TreeNode(4);
        root.right.left.right = new TreeNode(4);
        boolean result = isSymmetric(root);
        System.out.println(result); // 输出true,表示该二叉树是对称的
    }

python

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def isSymmetric(root: TreeNode) -> bool:
    if root is None:
        return True
    return check(root.left, root.right) and isSymmetric(root.left) and isSymmetric(root.right)

def check(left: TreeNode, right: TreeNode) -> bool:
    if left is None and right is None:
        return True # 如果左右子树都为空,则对称
    if left is None or right is None:
        return False # 如果左右子树有一个为空,则不对称
    if left.val != right.val:
        return False # 如果左右子树的值不相等,则不对称
    return check(left.left, right.right) and check(left.right, right.left) # 分别递归检查左右子树是否对称

c++

class TreeNode{
    public:
    int val;
    TreeNode* left;
    TreeNode* right;
    TreeNode(int val=0, TreeNode* left=nullptr, TreeNode* right=nullptr){
        this->val = val;
        this->left = left;
        this->right = right;
    }
};

bool isSymmetric(TreeNode* root){
    if(root == nullptr){
        return true;
    }
    return check(root->left, root->right) && isSymmetric(root->left) && isSymmetric(root->right);
}

bool check(TreeNode* left, TreeNode* right){
    if(left == nullptr && right == nullptr){
        return true; 
        // 如果左右子树都为空,则对称
    }
    if(left == nullptr || right == nullptr){
        return false; 
        // 如果左右子树有一个为空,则不对称
    }
    if(left->val != right->val){
        return false;
        // 如果左右子树的值不相等,则不对称
    }
    return check(left->left, right->right) && check(left->right, right->left);
    // 分别递归检查左右子树是否对称
}

go

type TreeNode struct {
    val int
    left *TreeNode
    right *TreeNode
}

func isSymmetric(root *TreeNode) bool {
    if root == nil {
        return true
    }
    return check(root.left, root.right) && isSymmetric(root.left) && isSymmetric(root.right)
}

func check(left *TreeNode, right *TreeNode) bool {
    if left == nil && right == nil {
        return true
        // 如果左右子树都为空,则对称
    }
    if left == nil || right == nil {
        return false
        // 如果左右子树有一个为空,则不对称
    }
    if left.val != right.val {
        return false
        // 如果左右子树的值不相等,则不对称
    }
    return check(left.left, right.right) && check(left.right, right.left)
    // 分别递归检查左右子树是否对称
}

rust

type TreeNode struct {
    val: i32,
    left: Option<Box<TreeNode>>,
    right: Option<Box<TreeNode>>,
}

fn is_symmetric(root: Option<&Box<TreeNode>>) -> bool {
    match root {
        None => true,
        Some(node) => check(&node.left, &node.right) && is_symmetric(node.left.as_ref()) && is_symmetric(node.right.as_ref())
    }
}

fn check(left: &Option<Box<TreeNode>>, right: &Option<Box<TreeNode>>) -> bool {
    match (left, right) {
        (None, None) => true,
        (None, _) | (_, None) => false,
        (Some(l), Some(r)) => l.val == r.val && check(&l.left, &r.right) && check(&l.right, &r.left)
    }
}

js

type TreeNode = class {
    constructor(val, left=null, right=null) {
        this.val = val;
        this.left = left;
        this.right = right;
    }
}

function isSymmetric(root) {
    function check(left, right) {
        if (!left && !right) {
            return true;
        }
        if (!left || !right) {
            return false;
        }
        return left.val == right.val && check(left.left, right.right) && check(left.right, right.left);
    }
    if (!root) {
        return true;
    }
    return check(root.left, root.right) && isSymmetric(root.left) && isSymmetric(root.right);
}

  1. 实现单例模式,要求线程安全。
  2. 实现冒泡排序,选择排序,插入排序。并分析三种排序算法的时间复杂度。
  3. 给你两个有序整数数组nums1 和 nums2,请你将 nums2 合并到nums1中,使得nums1 成为一个有序数组。
  4. 给定一个链表,判断是否有环。如果有环,返回入环节点,否则返回null。
  5. 编写一个函数,输入是一个无序链表,输出一个从小到大排序的有序链表。
  6. 实现一个LRU cache,要求get和set方法的时间复杂度为O(1)。
  7. 给出两个字符串s1和s2,请实现一个函数判断s2是否是s1的变位词。
  8. 实现队列的入队和出队操作,要求出队操作pop的时间复杂度为O(1)。

11.给定一个32位整数,返回该整数中1的个数。例如:给定整数11,返回2。给定整数128,返回1。

利用n & (n - 1)会将n的最后一个1变为0的特性。

每循环一次,就找到一个1,并将其变为0。循环终止的条件是n变为0,count的值就是n中1的个数。例如:

n = 11,

11 & (11 - 1) = 11 & 10 = 10   // 找到一个1,count变为1

10 & (10 - 1) = 10 & 9 = 8     // 找到一个1,count变为2

8 & (8 - 1) = 8 & 7 = 0        // n变为0,循环终止,count值为2 n = 128

128 & (128 - 1) = 128 & 127 = 0   // 找到一个1,count变为1,n变为0,循环终止,count值为1所以时间复杂度是O(k),k是n中1的个数。空间复杂度O(1)。

java

public int countOnes(int n) {
    int count = 0;
    while (n != 0) {
        n &= (n - 1);
        count++;
    }
    return count;
}

python

def countOnes(n):
    count = 0
    while n != 0:
        n &= (n - 1)
        count += 1
    return count

c++

public:
    int countOnes(int n) {
        int count = 0;
        while (n != 0) {
            n &= (n - 1);
            count++;
        }
        return count;
    }

go

public:
    func countOnes(n int) int {
        count := 0
        for n != 0 {
            n &= (n - 1)
            count++
        }
        return count
    } 

rust

pub fn count_ones(n: i32) -> i32 {
    let mut count = 0;
    let mut m = n;
    while m != 0 {
        m &= m - 1;
        count += 1;
    }
    count
}
目录
相关文章
|
3天前
|
编译器 开发工具 C++
【Python】已解决error: Microsoft Visual C++ 14.0 or greater is required. Get it with “Microsoft C++ Build
【Python】已解决error: Microsoft Visual C++ 14.0 or greater is required. Get it with “Microsoft C++ Build
22 0
|
10天前
|
算法 Java C++
C++和Python在内存管理上的主要区别是什么?
【7月更文挑战第2天】C++和Python在内存管理上的主要区别是什么?
11 1
|
9天前
|
Rust 开发工具 Android开发
flutter 调用c++,rust
flutter 调用c++,rust
|
10天前
|
存储 Java 程序员
Python和C++在内存管理方面有什么不同?
【7月更文挑战第2天】Python和C++在内存管理方面有什么不同?
13 0
|
10天前
|
Java C++ 开发者
如何根据项目需求选择使用C++还是Python进行内存管理?
【7月更文挑战第2天】如何根据项目需求选择使用C++还是Python进行内存管理?
14 0
|
10天前
|
算法 Java C++
C++和Python在内存分配策略上的主要区别是什么?
【7月更文挑战第2天】C++和Python在内存分配策略上的主要区别是什么?
8 0
|
10天前
|
Java 程序员 C++
C++和Python在内存分配、释放以及垃圾回收机制上有何不同?
【7月更文挑战第2天】C++和Python在内存分配、释放以及垃圾回收机制上有何不同?
11 0
|
10天前
|
机器学习/深度学习 Java 程序员
Python和C++的区别?
【7月更文挑战第2天】Python和C++的区别?
6 0
|
算法 前端开发 小程序
Python | C++、Java、Linux、Go、前端、算法资料分享
Python | C++、Java、Linux、Go、前端、算法资料分享
Python | C++、Java、Linux、Go、前端、算法资料分享
|
4天前
|
安全 Python
告别低效编程!Python线程与进程并发技术详解,让你的代码飞起来!
【7月更文挑战第9天】Python并发编程提升效率:**理解并发与并行,线程借助`threading`模块处理IO密集型任务,受限于GIL;进程用`multiprocessing`实现并行,绕过GIL限制。示例展示线程和进程创建及同步。选择合适模型,注意线程安全,利用多核,优化性能,实现高效并发编程。
18 3