2022.4.24腾讯笔试记录

腾讯笔试是五道题目,两个小时。

3道ACM模式,两道核心代码模式。

第1题

题目描述

有n个长度相等由数字组成的字符串,从上往下读,并排序,输出新的数字字符串,去掉前导0。

示例1
输入
3
0123
1234
2345
输出
12 123 234 345
思路分析

简单的字符串拆分拼接,以及list排序。

参考代码
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;

public class Main1 {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        in.nextLine();
        String[] str = new String[n];
        for (int i = 0; i < n; i++) {
            str[i] = in.nextLine();
        }
        int m = str[0].length();
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < m; i++) {
            String num = "";
            for (int j = 0; j < n; j++) {
                num += str[j].charAt(i);
            }
            list.add(Integer.parseInt(num));
        }
        Collections.sort(list);
        for (int i = 0; i < list.size(); i++) {
            if (i == list.size() - 1) {
                System.out.println(list.get(i));
            } else {
                System.out.print(list.get(i) + " ");
            }
        }
    }
}

第2题

题目描述

一个长度为n的数组a,数组下标从1~n。每一次将a中所有下标为非质数的元素进行删除,即ai且i不为质数。在删完之后,将数组a重新按顺序拼接起来,不断循环,直到数组大小为1,计算数组最后剩下的元素的值。

注:1不是质数
(本题是核心模式)

示例1
输入
[1,2,3,4]
输出
3
思路分析

本题是核心代码模式,这里自己写了输入进行测试。首先判断索引是不是质数,是质数的对应的索引-1加入list。然后循环计算。

参考代码
import java.util.ArrayList;
import java.util.List;

public class Main2 {
    public static void main(String[] args) {

        int a[] = new int[]{1,2,3,4};
        System.out.println(getNumber(a));
    }
    public static int getNumber(int[] a) {
        int n = a.length;
        List<Integer> list = new ArrayList<>();
        for (int i = 2; i < n; i++) {
            if (isPrime(i)) {  // 将质数索引加入list
                list.add(i - 1);
            }
        }
        while (n != 1) {
            int k = 0;
            for (int i = 0; i < list.size() && list.get(i) < n; i++) {
                a[k++] = a[list.get(i)];
            }
            n = k;
        }
        return a[0];
    }
    public static boolean isPrime(int x){  // 判断是不是质数
        int m = (int)(Math.sqrt(x) + 1);
        for (int i = 2; i < m; i++) {
            if (x % i == 0) {
                return false;
            }
        }
        return true;
    }
}

第3题

题目描述

有n个战士站成1排,编号为1,2……n,战士的战斗力等于编号,一些战士只会进攻,一些战士只会防守,将他们从某个点分成两个阵营,假设这个点为pos,则0~pos的是进攻组,只算攻击力,pos+1~n的是防御组,只算防御力。pos可以取0~n。假设第一个阵营中进攻的战力总和为w,第二个阵营防守战力总和为v,求|w-v|最小值。

输入描述

第一行输入一个整数n,表示战士数量

第二行给一个字符串s,仅由0和1组成,0代表进攻,1代表防守。

输出描述

输出|w-v|最小值

示例1
输入
4
0011
输出
1
思路分析

前缀和,计算进攻方的战力总和,防守方的战力总和,再逐个求差值绝对值最小值。注意全进攻和全防守的情况。

参考代码
import java.util.Scanner;

public class Main3 {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        in.nextLine();
        String str = in.nextLine();
        long[] a = new long[n + 1];
        long[] d = new long[n + 1];
        for (int i = 1; i <= n; i++) {
            a[i] = a[i - 1];
            d[i] = d[i - 1];
            if (str.charAt(i - 1) == '0') {
                a[i] += i;
            } else {
                d[i] += i;
            }
        }
        long res = Math.min(a[n], d[n]);  // 全进攻全防守
        for (int i = 1; i < n; i++) {
            res = Math.min(res, Math.abs(a[i] - (d[n] - d[i])));
        }
        System.out.println(res);
    }
}

第4题

题目描述

给出一个链表数组,该链表数组均是某一个环状链表的一部分,请将这些链表组合并成环状链表,然后需要找到一个位置,使得这个位置将环切开后,按照顺序或逆序遍历这个环,形成的链字典顺序尽量小,并返回这条链。

  1. 链表字典序的定义:对于两个链表a,b,从头节点到尾节点遍历,找到第一个不相同的节点值,如果存在i使得a[i].val < b[i].val,那么就让我a的字典序比较小。比如链表{1,2,3}<链表{1,2,4},链表{3,4,5}<链表{6,7}。
  2. 环状链表不存在相同的节点值
  3. 该题环状链表节点个数最小为2
  4. 每个链表都是环状链表上的顺时针的一部分
  5. 给定的链表数组一定能组成一个环状链表
    (本题是核心模式)
示例1
输入
[{1,2,3},{2,3,4},{4,1}]
输出
{1,2,3,4}
示例2
输入
[{3,7,4},{7,4,5,1,10,3}]
输出
{1,5,4,7,3,10}
思路分析

链表中结点的值唯一,使用哈希表记录结点的前驱和后继,并记录最小值,然后从最小值开始遍历,并判断最小值的前驱和后继哪个更小,从更小的开始顺序遍历。

参考代码
import java.util.*;

class ListNode {
    int val;
    ListNode next = null;
    public ListNode(int val) {
        this.val = val;
    }
}

public class Main4 {

    public ListNode solve (ListNode[] a) {
        // write code here
        Map<ListNode, ListNode> map = new HashMap<>();
        Map<Integer, ListNode> map2 = new HashMap<>();
        for (ListNode node : a) {
            ListNode pre = map2.computeIfAbsent(node.val, v -> new ListNode(v));
            node = node.next;
            while (node != null) {
                ListNode mNode = map2.computeIfAbsent(node.val, v -> new ListNode(v));
                map.put(pre, mNode);
                pre = mNode;
                node = node.next;
            }
        }
        for (Map.Entry<ListNode, ListNode> entry : map.entrySet()) {  // 对哈希表进行排序
            entry.getKey().next = entry.getValue();
        }
        ListNode head = map2.get(a[0].val);
        ListNode minNode = head;
        ListNode p = head.next;
        while (p != head) {
            if (p.val < minNode.val) {
                minNode = p;
            }
            p = p.next;
        }
        // 找到minNode最后的节点
        ListNode node = minNode;
        while (node.next != minNode) {
            node = node.next;
        }
        int preVal = node.val;
        ListNode next = minNode.next;
        if (next.val < preVal) {
            node.next = null;
            return minNode;
        }else {
            // 反转链表
            minNode.next = null;
            reverse(next);
            return minNode;
        }
    }

    private void reverse(ListNode head) {
        ListNode pre = null;
        while (head != null) {
            ListNode next = head.next;
            head.next = pre;
            pre = head;
            head = next;
        }
    }
}

参考:腾讯4.24笔试

第5题

题目描述

现有一长度为n的数组a,表示每支股票的价格,每天最多买入或卖出该支股票的1手股票,买入或卖出没有手续费,且卖出股票前必须手里已经有股票才能卖出,但是持有的股票数目不受限制,并且初始资金为m元,在任意时刻不能进行透支,所以资金必须始终大于等于0,请问在n天结束后,拥有最大总资产是多少?(最大总资产为持有现金+持有的股票价格)

输入描述

第一行两个整数,n,m
第二行n个整数{ai},其中ai表示股票在第i天的售价

输出描述

输出n天结束后,拥有最大总资产

示例1
输入
6 2
2 3 1 1 1 2
输出
6
说明

第1天买入1手,第2天卖出1手,第3,4,5天都买入1手,最后总持有3手股票,股票价格为2,总资产为6

示例2
输入
3 2
1 1 4
输出
8
说明

第一天买入,第二天买入,第三天继续持有,总共持有两手股票,股票价格为4,总资产为8

示例3
输入
3 100
10 9 8
输出
100
说明

股票一直在下跌,都不买入,现金为100,股票为0,总资产为0

思路分析

看到股票问题,首先想到leetcode上的股票买卖问题,122. 买卖股票的最佳时机 II,但不同的是,买卖股票的最佳时机 II中在任何时候 最多 只能持有 一股 股票。而本题中同一时刻可以持有多手股票。

但思路相同,动态规划求解。

设dp[i][j]为第i天持有j个股票能拥有的最大现金。

每天的操作有3种,无操作,买入1手,卖出1手。买入的时候有限制条件,不能透支。则dp[i][j] = Math.min(dp[i-1][j] , dp[i][j+1] +prices[i] , dp[i][j-1]-prices[i])

需要注意的是,股票的价格可能很大,所以定义dp数组为long。

参考代码
import java.util.*;

public class Main5 {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int N = in.nextInt();
        int price = in.nextInt();
        int[] prices = new int[N];
        for (int i = 0; i < N; i++) {
            prices[i] = in.nextInt();
        }
        long[][] dp = new long[N][N];  // 注意这里定义为long
        // dp[i][j]为第i天持有j个股票能拥有的最大现金额度,n天最多n-1支股票
        Arrays.fill(dp[0], -1);
        dp[0][0] = price; // 第0天,0注股票price元
        if (price >= prices[0]) {
            dp[0][1] = price - prices[0];
        }
        for (int i = 1; i < N; i++) {
            for (int j = 0; j < N; j++) {
                dp[i][j] = dp[i - 1][j];  // 无操作,不买入也不卖出
                if (j > 0) { // 买入1注,且金额足够
                    if (dp[i - 1][j - 1] != -1 && dp[i - 1][j - 1] >= prices[i]) {
                        dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - 1] - prices[i]);
                    }
                }
                if (j < N - 1) {  // 卖出1注
                    if (dp[i - 1][j + 1] != -1) {
                        dp[i][j] = Math.max(dp[i][j], dp[i - 1][j + 1] + prices[i]);
                    }
                }
            }
        }
        long res = 0;
        for (int i = 0; i < N; i++) {
            if (dp[N - 1][i] == -1) continue;
            res = Math.max(res, dp[N - 1][i] + i * prices[N - 1]);
        }
        System.out.println(res);
    }
}
  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值