【灵犀互娱笔试题汇总】[全网首发] 2024-03-30-灵犀互娱春招笔试题-三语言题解(CPP/Python/Java)

🍭 大家好这里是KK爱Coding ,一枚热爱算法的程序员

✨ 本系列打算持续跟新灵犀互娱近期的春秋招笔试题汇总~

💻 ACM银牌🥈| 多次AK大厂笔试 | 编程一对一辅导

👏 感谢大家的订阅➕ 和 喜欢💗

01.Z 字形编码

问题描述

LYA 正在研究一种新的编码方式,称为 Z 字形编码。给定两个无符号 4 4 4 字节长度的整数 x x x y y y,Z 字形编码的计算规则如下:

  1. x x x y y y 转换为二进制形式。
  2. x x x y y y 的二进制形式中交替取位,每次取 1 1 1 位,先从 x x x 的高位开始取,然后从 y y y 的高位开始取,依次类推,直到取完 x x x y y y 的所有二进制位。
  3. 将取出的二进制位按顺序拼接,得到一个新的二进制数 z z z
  4. z z z 转换为无符号 8 8 8 字节长度的整数作为编码结果。

现在,LYA 有一些整数对需要进行 Z 字形编码,她想请你帮忙计算编码结果。

输入格式

第一行包含一个正整数 n n n,表示需要编码的整数对数量。

接下来 n n n 行,每行包含两个无符号 4 4 4 字节长度的整数 x x x y y y,表示一个需要编码的整数对。

输出格式

输出共 n n n 行,每行一个无符号 8 8 8 字节长度的整数,表示对应整数对的 Z 字形编码结果。

样例输入

3
18 52
178 532
321 943

样例输出

1816
297752
484439

数据范围

  • 1 ≤ n ≤ 1 0 5 1 \le n \le 10^5 1n105
  • 0 ≤ x , y < 2 32 0 \le x, y < 2^{32} 0x,y<232

题解

这道题考查的是位运算和二进制操作。我们可以分别从 x x x y y y 的高位开始,依次取出一个二进制位,然后将其拼接到结果 z z z 的二进制形式中。重复这个过程,直到取完 x x x y y y 的所有二进制位。

具体实现时,我们可以用移位操作和位与操作来取出 x x x y y y 的二进制位。每次取出一位后,将 x x x y y y 右移 1 1 1 位,直到 x x x y y y 都变为 0 0 0。同时,我们用一个变量 z z z 来存储编码结果,每取出一位,就将其拼接到 z z z 的末尾,并将 z z z 左移 1 1 1 位。

时间复杂度为 O ( n ) O(n) O(n),其中 n n n 为整数对的数量。单次编码的时间复杂度为 O ( 1 ) O(1) O(1),因为整数的二进制位数是固定的。空间复杂度为 O ( 1 ) O(1) O(1)

参考代码

  • Python
def zorder(x, y):
    z = 0
    for i in range(32):
        z = (z << 1) | ((x >> (31 - i)) & 1)
        z = (z << 1) | ((y >> (31 - i)) & 1)
    return z

n = int(input())
for _ in range(n):
    x, y = map(int, input().split())
    print(zorder(x, y))
  • Java
import java.io.*;
import java.util.*;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine());
        while (n-- > 0) {
            String[] xy = br.readLine().split(" ");
            int x = Integer.parseInt(xy[0]);
            int y = Integer.parseInt(xy[1]);
            System.out.println(zorder(x, y));
        }
    }
    
    private static long zorder(int x, int y) {
        long z = 0;
        for (int i = 31; i >= 0; i--) {
            z = (z << 1) | ((x >> i) & 1);
            z = (z << 1) | ((y >> i) & 1);
        }
        return z;
    }
}
  • Cpp
#include <iostream>

using namespace std;

typedef unsigned int uint;
typedef unsigned long long ull;

ull zorder(uint x, uint y) {
    ull z = 0;
    for (int i = 31; i >= 0; i--) {
        z = (z << 1) | ((x >> i) & 1);
        z = (z << 1) | ((y >> i) & 1);
    }
    return z;
}

int main() {
    int n;
    cin >> n;
    while (n--) {
        uint x, y;
        cin >> x >> y;
        cout << zorder(x, y) << endl;
    }
    return 0;
}

02.单词翻转

题目描述

K小姐正在学习英语,一次考试中遇到一道单词翻转的题目。给定一个由多个单词构成的英文句子,要求将句子中的每个单词都翻转后输出,同时保持单词在句子中的相对位置不变。

输入格式

第一行包含一个正整数 T T T,表示总共有 T T T 组测试数据。

接下来 T T T 行,每行一个字符串,表示一个由多个单词构成的英文句子。每个句子的长度不超过 1023 1023 1023 个字符。

输出格式

对于每组测试数据,输出一行,每行包含翻转后的句子,单词之间用一个空格隔开。

样例输入

3
game
hello world
welcome to lingxi

样例输出

emag
olleh dlrow
emoclew ot ixgnil

数据范围

  • 1 ≤ T ≤ 100 1 \leq T \leq 100 1T100
  • 句子中单词数不超过 100 100 100
  • 单词由小写英文字母构成
  • 相邻单词之间用一个空格隔开,句首和句尾没有多余空格

题解

本题考查字符串的处理能力。我们可以按照如下步骤解决该问题:

  1. 读入一行字符串,表示一个句子。
  2. 将句子按照空格分割成若干个单词。
  3. 对每个单词进行翻转操作。
  4. 将翻转后的单词按照原有顺序拼接成新的句子并输出。

具体而言,我们可以使用字符串流(stringstream)来方便地实现单词的分割。将原句子作为字符串流的输入,然后通过 “>>” 运算符依次读取单词并存储到字符串 s 中。对于每个读入的单词,先进行翻转,再将翻转后的单词存储到结果数组中。

最后,遍历结果数组,将单词按顺序输出,相邻单词之间用空格隔开即可。

本题的时间复杂度为 O ( n ) O(n) O(n),其中 n n n 为句子的总字符数。空间复杂度也为 O ( n ) O(n) O(n)

参考代码

  • Python
t = int(input())
for _ in range(t):
    line = input().split()
    res = [word[::-1] for word in line]
    print(' '.join(res))
  • Java
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int t = sc.nextInt();
        sc.nextLine();
        
        while (t-- > 0) {
            String line = sc.nextLine();
            String[] words = line.split("\\s+");
            
            List<String> res = new ArrayList<>();
            for (String word : words) {
                res.add(new StringBuilder(word).reverse().toString());
            }
            
            System.out.println(String.join(" ", res));
        }
    }
}
  • Cpp
#include <iostream>
#include <sstream>
#include <vector>
#include <algorithm>

using namespace std;

void solve() {
    string line;
    getline(cin, line);
    stringstream ss(line);
    vector<string> res;

    string word;
    while (ss >> word) {
        reverse(word.begin(), word.end());
        res.push_back(word);
    }

    for (int i = 0; i < res.size(); i++) {
        cout << res[i];
        if (i < res.size() - 1) {
            cout << " ";
        }
    }
    cout << endl;
}

int main() {
    int t;
    cin >> t;
    cin.ignore();

    while (t--) {
        solve();
    }

    return 0;
}

03.符文匹配

问题描述

K小姐踏上了一场充满神秘的符文之旅。她手中拥有记录着一串神秘符文 s 1 s_1 s1。经过漫长的探险,K小姐找到了另外一串更长的神秘符文序列 s 2 s_2 s2。现在,她需要判断 s 2 s_2 s2 中是否存在一个子串,使得该子串恰好由 s 1 s_1 s1 的所有字符按某种顺序组成,且每个字符只使用一次。

换言之,K小姐需要判断 s 1 s_1 s1 的任意一个排列是否为 s 2 s_2 s2 的子串。

输入格式

第一行包含一个正整数 T T T,表示测试数据的组数。

每组数据包含两行:
第一行为字符串 s 1 s_1 s1
第二行为字符串 s 2 s_2 s2

输出格式

对于每组测试数据,如果 s 2 s_2 s2 中存在 s 1 s_1 s1 的排列作为子串,则输出 true,否则输出 false

样例输入

2
lingxi
aerlxngli
lingxi
aerlxngixi

样例输出

true
false

数据范围

  • 1 ≤ T ≤ 100 1 \le T \le 100 1T100
  • 1 ≤ ∣ s 1 ∣ ≤ ∣ s 2 ∣ ≤ 1 0 5 1 \le |s_1| \le |s_2| \le 10^5 1s1s2105
  • 字符串 s 1 s_1 s1 s 2 s_2 s2 仅包含小写英文字母

题解

这道题可以用滑动窗口 + 哈希表的思路来解决。

首先,我们统计字符串 s 1 s_1 s1 中每个字符出现的次数,用哈希表 l l l 存储。

然后,我们在字符串 s 2 s_2 s2 上维护一个长度为 ∣ s 1 ∣ |s_1| s1 的滑动窗口,用另一个哈希表 r r r 统计窗口内每个字符出现的次数。

初始时,滑动窗口位于字符串 s 2 s_2 s2 的最左端。我们先统计窗口内字符出现的次数,如果此时两个哈希表相同,说明找到了一个合法的排列,可以直接返回 true

否则,我们不断右移滑动窗口,每次移动时:

  1. 去掉窗口最左端的字符,同时将哈希表 r r r 中对应的计数减 1 1 1,如果减到 0 0 0 则直接从哈希表中删除这个字符;
  2. 将窗口最右端新加入的字符加到哈希表 r r r 中,计数加 1 1 1

然后比较两个哈希表是否相同,如果相同则说明找到了一个合法排列,返回 true

如果滑动窗口移动到最右端还没有找到合法排列,则返回 false

算法的时间复杂度为 O ( ∣ s 2 ∣ ) O(|s_2|) O(s2),空间复杂度为 O ( ∣ s 1 ∣ ) O(|s_1|) O(s1)

参考代码

  • Python
T = int(input())
for _ in range(T):
    s1 = input().strip()
    s2 = input().strip()
    n, m = len(s1), len(s2)
    
    if m < n:
        print("false") 
        continue
        
    l, r = {}, {}
    for c in s1:
        l[c] = l.get(c, 0) + 1
        
    for c in s2[:n]:
        r[c] = r.get(c, 0) + 1
        
    if l == r:
        print("true")
        continue
        
    for i in range(n, m):
        r[s2[i-n]] -= 1
        if r[s2[i-n]] == 0:
            del r[s2[i-n]]
            
        r[s2[i]] = r.get(s2[i], 0) + 1
        
        if l == r:
            print("true") 
            break
    else:
        print("false")
  • Java
import java.io.*;
import java.util.*;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int T = Integer.parseInt(br.readLine());
        
        while (T-- > 0) {
            String s1 = br.readLine();
            String s2 = br.readLine();
            int n = s1.length(), m = s2.length();
            
            if (m < n) {
                System.out.println("false");
                continue;
            }
            
            Map<Character, Integer> l = new HashMap<>(), r = new HashMap<>();
            for (char c : s1.toCharArray()) {
                l.put(c, l.getOrDefault(c, 0) + 1);
            }
            
            for (int i = 0; i < n; i++) {
                char c = s2.charAt(i);
                r.put(c, r.getOrDefault(c, 0) + 1);
            }
            
            if (check(l, r)) {
                System.out.println("true");
                continue;
            }
            
            for (int i = n; i < m; i++) {
                char prev = s2.charAt(i - n), curr = s2.charAt(i);
                r.put(prev, r.get(prev) - 1);
                if (r.get(prev) == 0) {
                    r.remove(prev);
                }
                r.put(curr, r.getOrDefault(curr, 0) + 1);
                
                if (check(l, r)) {
                    System.out.println("true");
                    break;
                }
            }
            
            if (!check(l, r)) {
                System.out.println("false");
            }
        }
    }
    
    private static boolean check(Map<Character, Integer> l, Map<Character, Integer> r) {
        if (l.size() != r.size()) {
            return false;
        }
        for (char c : l.keySet()) {
            if (!r.containsKey(c) || !l.get(c).equals(r.get(c))) {
                return false;
            }
        }
        return true;
    }
}
  • Cpp
#include <iostream>
#include <string>
#include <unordered_map>

using namespace std;

bool check(unordered_map<char, int>& l, unordered_map<char, int>& r) {
    if (l.size() != r.size()) {
        return false;
    }
    for (auto& [c, cnt] : l) {
        if (!r.count(c) || r[c] != cnt) {
            return false;
        }
    }
    return true;
}

int main() {
    int T;
    cin >> T;
    while (T--) {
        string s1, s2;
        cin >> s1 >> s2;
        int n = s1.size(), m = s2.size();
        
        if (m < n) {
            cout << "false" << endl;
            continue;
        }
        
        unordered_map<char, int> l, r;
        for (char c : s1) {
            l[c]++;
        }
        
        for (int i = 0; i < n; i++) {
            r[s2[i]]++;
        }
        
        if (check(l, r)) {
            cout << "true" << endl;
            continue;
        }
        
        for (int i = n; i < m; i++) {
            r[s2[i-n]]--;
            if (r[s2[i-n]] == 0) {
                r.erase(s2[i-n]);
            }
            r[s2[i]]++;
            
            if (check(l, r)) {
                cout << "true" << endl;
                break;
            }
        }
        
        if (!check(l, r)) {
            cout << "false" << endl;
        }
    }
    
    return 0;
}

04.魔法学徒的算术考试

题目描述

在魔法学校中,学徒们正在进行一场特殊的算术考试。这场考试的题目由数字和运算符组成,运算符包括加法 + + +、减法 − - 、乘法 ∗ * 和除法 / / /,其中加法和减法的优先级高于乘法和除法。学徒们需要按照题目给出的算术表达式计算出最终的结果。

输入格式

输入一行,包含一个由数字、运算符 + + + − - ∗ * / / /,以及空格组成的算术表达式。

输出格式

输出一个整数,表示算术表达式的计算结果。

样例输入

1 + 2 * 3 - 4 / 2

样例输出

5

数据范围

  • 表达式中的所有数字均为正整数,且不超过 1 0 9 10^9 109
  • 表达式的长度不超过 100 100 100
  • 保证表达式合法,且计算过程中和最终结果均不超过 2 31 − 1 2^{31}-1 2311

题解

本题需要根据题目描述的运算符优先级,对算术表达式进行求值。我们可以使用两个栈 num_stackop_stack 分别存储数字和运算符,具体步骤如下:

  1. 将字符串中的空格去掉,方便后续处理。

  2. 从左到右遍历字符串:

    • 如果当前字符为数字,则连续读取数字并将其转化为整数,然后压入 num_stack
    • 如果当前字符为左括号 (,则直接压入 op_stack
    • 如果当前字符为右括号 ),则不断弹出 op_stack 的运算符并进行计算,直到遇到左括号为止。计算结果压入 num_stack
    • 如果当前字符为运算符,则:
      • 如果 op_stack 为空,或者栈顶运算符为左括号,或者当前运算符优先级大于栈顶运算符,则直接压入 op_stack
      • 否则,不断弹出 op_stack 的运算符并进行计算,直到当前运算符优先级大于栈顶运算符。然后将当前运算符压入 op_stack
  3. 遍历完字符串后,将 op_stack 中剩余的运算符依次弹出并进行计算。

  4. 最后 num_stack 中剩下的唯一一个数字即为表达式的结果。

时间复杂度 O ( n ) O(n) O(n),空间复杂度 O ( n ) O(n) O(n)。其中 n n n 为算术表达式的长度。

参考代码

  • Python
mp = {'+': 3, '-': 3, '*': 2, '/': 2}

def calc(a, b, op):
    if op == '+':
        return a + b
    elif op == '-':
        return a - b
    elif op == '*':
        return a * b
    else:
        return a // b

s = input().replace(' ', '')
num_stack = []
op_stack = []

i = 0
while i < len(s):
    if s[i].isdigit():
        x = 0
        while i < len(s) and s[i].isdigit():
            x = x * 10 + int(s[i])
            i += 1
        num_stack.append(x)
    elif s[i] == '(':
        op_stack.append(s[i])
        i += 1
    elif s[i] == ')':
        while op_stack and op_stack[-1] != '(':
            num_b = num_stack.pop()
            num_a = num_stack.pop()
            op = op_stack.pop()
            num_stack.append(calc(num_a, num_b, op))
        op_stack.pop()
        i += 1
    else:
        while op_stack and mp[op_stack[-1]] >= mp[s[i]]:
            num_b = num_stack.pop()
            num_a = num_stack.pop()
            op = op_stack.pop()
            num_stack.append(calc(num_a, num_b, op))
        op_stack.append(s[i])
        i += 1

while op_stack:
    num_b = num_stack.pop()
    num_a = num_stack.pop()
    op = op_stack.pop()
    num_stack.append(calc(num_a, num_b, op))

print(num_stack[0])
  • Java
import java.io.*;
import java.util.*;

public class Main {
    static Map<Character, Integer> mp = new HashMap<>();
    static {
        mp.put('+', 3);
        mp.put('-', 3);
        mp.put('*', 2);
        mp.put('/', 2);
    }

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String str = br.readLine().replaceAll("\\s+", "");
        Deque<Integer> numStack = new ArrayDeque<>();
        Deque<Character> opStack = new ArrayDeque<>();

        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            if (Character.isDigit(c)) {
                int x = 0, j = i;
                while (j < str.length() && Character.isDigit(str.charAt(j))) {
                    x = x * 10 + (str.charAt(j) - '0');
                    j++;
                }
                numStack.push(x);
                i = j - 1;
            } else if (c == '(') {
                opStack.push(c);
            } else if (c == ')') {
                while (!opStack.isEmpty() && opStack.peek() != '(') {
                    calc(numStack, opStack);
                }
                opStack.pop();
            } else {
                while (!opStack.isEmpty() && opStack.peek() != '(' && mp.get(opStack.peek()) >= mp.get(c)) {
                    calc(numStack, opStack);
                }
                opStack.push(c);
            }
        }

        while (!opStack.isEmpty()) {
            calc(numStack, opStack);
        }

        System.out.println(numStack.pop());
    }

    private static void calc(Deque<Integer> numStack, Deque<Character> opStack) {
        int b = numStack.pop(), a = numStack.pop();
        char op = opStack.pop();
        int c = 0;
        if (op == '+') c = a + b;
        else if (op == '-') c = a - b;
        else if (op == '*') c = a * b;
        else c = a / b;
        numStack.push(c);
    }
}
  • Cpp
#include <iostream>
#include <string>
#include <stack>
#include <unordered_map>
using namespace std;

unordered_map<char, int> mp{{'+', 3}, {'-', 3}, {'*', 2}, {'/', 2}};

void calc(stack<int>& num_stack, stack<char>& op_stack) {
    int b = num_stack.top(); num_stack.pop();
    int a = num_stack.top(); num_stack.pop();
    char op = op_stack.top(); op_stack.pop();
    int c = 0;
    if (op == '+') c = a + b;
    else if (op == '-') c = a - b;
    else if (op == '*') c = a * b;
    else c = a / b;
    num_stack.push(c);
}

int main() {
    string str;
    getline(cin, str);
    string s;
    for (char c : str) {
        if (c != ' ') {
            s += c;
        }
    }

    stack<int> num_stack;
    stack<char> op_stack;
    for (int i = 0; i < s.size(); i++) {
        if (isdigit(s[i])) {
            int x = 0, j = i;
            while (j < s.size() && isdigit(s[j])) {
                x = x * 10 + (s[j] - '0');
                j++;
            }
            num_stack.push(x);
            i = j - 1;
        } else if (s[i] == '(') {
            op_stack.push(s[i]);
        } else if (s[i] == ')') {
            while (op_stack.size() && op_stack.top() != '(') {
                calc(num_stack, op_stack);
            }
            op_stack.pop();
        } else {
            while (op_stack.size() && op_stack.top() != '(' && mp[op_stack.top()] >= mp[s[i]]) {
                calc(num_stack, op_stack);
            }
            op_stack.push(s[i]);
        }
    }

    while (op_stack.size()) {
        calc(num_stack, op_stack);
    }

    cout << num_stack.top() << endl;
    return 0;
}

写在最后

📧 KK这边最近正在收集近一年互联网各厂的笔试题汇总,如果有需要的小伙伴可以关注后私信一下 KK领取~

在这里插入图片描述

  • 27
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
2023年3月11日,美团春季招聘笔试中共包含五道编程题目。以下是对每道题目的简要说明: 1. 题目一:这道题目要求解决一个数字统计的问题。可能涉及到的知识点包括数据结构、循环和条件判断等。解决问题的思路可能是使用字典等数据结构来保存统计结果,并使用循环逐个读取输入数据并进行统计。 2. 题目二:这道题目可能是一个字符串处理的问题。需要使用字符串的方法进行操作,如提取、拼接、查找和替换等。可能的解决思路包括使用正则表达式、切片和遍历等。 3. 题目:这道题目可能涉及到算法和数据结构的知识。可能是一道涉及到数组、链表、树等数据结构的问题。解决思路可能包括遍历、递归、搜索和排序等。 4. 题目四:这道题目可能是一个动态规划的问题。需要根据给定的条件和规则,通过动态规划的方式求解问题。解决思路包括定义状态和转移方程,使用递推或记忆化搜索进行求解。 5. 题目五:这道题目可能是一个图论或网络问题。需要根据给定的图或网络结构,解决一个相关的问题。可能涉及到广度优先搜索、深度优先搜索、最短路径等知识。解决思路可能包括使用图或网络的相关算法进行求解。 以上只是对这五道编程题目的一些可能情况进行的简要描述,具体的题目内容可能会有所不同。希望这些信息能对你有所帮助!
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值