腾讯(Tencent)2022实习笔试算法题
第一题
题目描述:
牛牛有n个长度相等由数字组成的字符串,牛牛将他们一行一行排列在一起,从上到下读数,可以将这n个字符串读出了一些数字字符串,把这些字符串记录下来并排序输出,去掉前导0.
输入描述:
第一行为n,表示由n个字符串。
接下来有n行,每行有一个字符串str。
1<=n<=9
1<str.length<=10^5
输出描述:
输出为一行,表示排序后的数字,每个数字以空格隔开。
示例1:
输入:
3
0123
1234
2345
输出:
12 123 234 345
说明:每一列从上到下读到的数字为012,123,234,345,去掉前导0之后排序结果如上。
示例2:
输入:
4
0000
0101
1011
0111
输出:
10 11 101 111
python代码:
if __name__ =='__main__':
n = int(input())
num = []
for i in range(n):
row = input()
num.append(row)
r = len(num[0])
l = len(num)
end_num = []
for i in range(len(num[0])):
s=0
for j in range(len(num)):
s+= int(num[j][i])*pow(10,l-j-1)
end_num.append(s)
end_num.sort()
print(end_num)
第二题:
牛牛有一个长度为n的的数组a,数组下标1-n,每次从a中所有下标为非质数的元素进行删除,即ai 且i不为质数,在删除完之后重新排序,不断循环直至剩余一个元素并输出。
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
// int a[] = new int[]{1,2,3,4};
int a[] = new int[]{3,1,1,4,5,6};
Main main = new Main();
System.out.println(main.getNumber(a));
}
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* @param a int整型一维数组
* @return int整型
*/
public int getNumber (int[] a) {
// write code here
int n = a.length;
List<Integer> pnums = getZ(n);
while (n!=1){
int k = 0;
for (int i = 0; i < pnums.size() && pnums.get(i)<n; i++) {
a[k++] = a[pnums.get(i)];
}
n = k;
}
return a[0];
}
public List<Integer> getZ(int n){
List<Integer> list = new ArrayList<>();
for (int i = 2; i < n; i++) {
if(isP(i)){
list.add(i-1);
}
}
/* System.out.print("{");
for (int i = 0; i < list.size()-1; i++) {
System.out.print(list.get(i)+",");
}
System.out.println(list.get(list.size()-1)+"}");*/
return list;
}
public boolean isP(int x){
for(int i = 2;i < (int)(Math.sqrt(x)+1);i++){
if(x%i==0){
return false;
}
}
return true;
}
}
第三题:
n个战士排成一排,分别编号为1,2,3,…n。战士的战斗力等于他的编号,有一些战士只会进攻,有一些战士只会防守,现在我们要将他们从某个点开始分成两个阵营,假设这个点pos,则编号为1,2,3…pos的战士为第一阵营,pos+1,pos+2…n为第二阵营,假设pos=0时,说明第一阵营没有战士,所有战士在第二阵营。令第一阵营为进攻方,第二个阵营为防守方,假设第一阵营中能够进攻的战士战斗力总和为w,第二个阵营中能够防守的战士战斗力总和为v,我们希望|w-v|的值最小,求最小值。
输入描述:
第一行输入一个正整数n, 表示战士数量(1<=n<=10^5)
第二行给出一个字符串s,仅由0或1组成,0表示这个战士只会进攻,1表示只会防守。
输出描述:
输出一行一个整数表示|w-v|的最小值。
示例1:
4
0011
输出:
1
示例2:
7
1000101
输出:
2
py代码:
if __name__ == '__main__':
N = int(input())
char = input()
mid_num=10000000
if N==1:
print(0)
else:
for i in range(len(char)+1):
w=0
v=0
pos = i #确定pos
for j in range(len(char)):
if j+1<=pos:
if int(char[j])==0:
w = w+j+1
else:
if int(char[j])==1:
v = v+j+1
if mid_num>=abs(w-v):
mid_num = abs(w-v)
print(mid_num)
def is_xunhuan(inputList):
for i in range(len(inputList)):
for j in range(len(inputList[i])):
第四题:
给出一个链表数组,该链表数组均是某一个环状链表的一部分,请你将这些链表数组合并成环状链表,然后需要找到一个位置,使得从这个位置将环切开后,按照顺序或者逆序遍历这个环,形成的链表字典序尽量小,并返回这条链。
1.链表字典序的定义:对于两个链表a,b,从头节点到尾节点遍历,找到第一个不相同的节点值,如果存在i使得a[i].val<b[i].val,那么我们认为,a的字典序是小于b的字典序的。
2.环状链表不存在相同的节点值。
3.该题环状链表节点个数最小为2。
4.每个链表都是在环状链表上的顺时针的一部分。
5.给定的链表数组一定能组成一个环状链表。
(本题是核心模式,不需要自己处理输入输出,完成函数即可)
示例1:
输入:
{{1,2,3},{2,3,4},{4,1}}
输出:
{1,2,3,4}
说明:形成的环状链表为1=>2=>3=>4=>1=>2.....,从1断开,顺序遍历,得到最小字典序数列。
示例2:
输入:
[{3,7,4},{7,4,5,1,10,3}]
输出:
{1,5,4,7,3,10}
java代码:
import java.util.*;
class ListNode {
int val;
ListNode next = null;
public ListNode(int val) {
this.val = val;
}
}
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* @param a ListNode类一维数组 指向每段碎片的开头
* @return ListNode类
*/
public ListNode solve(ListNode[] a) {
// write code here
HashMap<Integer, ListNode> nodeMap = new HashMap<>();
HashMap<Integer, Integer> preMap = new HashMap<>();
HashMap<Integer, Integer> nextMap = new HashMap<>();
HashMap<Integer, Boolean> visitedMap = new HashMap<>();
int min = Integer.MAX_VALUE;
for (int i = 0; i < a.length; i++) {
printList(a[i]);
for (ListNode p = a[i]; p != null; p = p.next) {
nodeMap.put(p.val, p);
if (p.next != null) {
preMap.put(p.next.val, p.val);
nextMap.put(p.val, p.next.val);
}
min = Math.min(min, p.val);
}
}
ListNode head = new ListNode(0);
head.next = null;
ListNode rear = head;
rear.next = nodeMap.get(min);
rear = rear.next;
rear.next = null;
visitedMap.put(min, true);
if (preMap.get(min) < nextMap.get(min)) {
//前驱小 从前驱走
while (!visitedMap.getOrDefault(preMap.get(min), false)) {
min = preMap.get(min);
rear.next = nodeMap.get(min);
rear = rear.next;
rear.next = null;
visitedMap.put(min, true);
}
} else {
//后继小 从后继走
//前驱小 从前驱走
while (!visitedMap.getOrDefault(nextMap.get(min), false)) {
min = nextMap.get(min);
rear.next = nodeMap.get(min);
rear = rear.next;
rear.next = null;
visitedMap.put(min, true);
}
}
printList(head);
return head.next;
}
public void printList(ListNode head) {
System.out.print("链表->{");
for (ListNode p = head; p != null; p = p.next) {
System.out.print(p.val+" ");
}
System.out.println("}");
}
}
第五题:
现在有一个长度为n的价格数组a,表示某只股票每天的价格,你每天最多买入或者卖出该只股票的1手股票,买入或者卖出没有手续费,且卖出股票前必须手里已经有股票才能卖出,但是持有的股票数目不受限制,并且初始资金为m元,你在任意时刻都不能进行透支,所以你的资金必须始>=0,请问你在第n天结束之后,拥有最大的总资产是多少?(总资产:股票数目*股票价格+现金)
输入描述:
第一行两个正整数n,m{1<=n<=2000, 1<=m<=10^9}。
第二行n个正整数{an}{1<=ai<=10^9}
输出描述:
输出n天结束之后,拥有的最大总资产。
示例1:
输入:
6 2
2 3 1 1 1 2
输出:
6
示例2:
输入:
3 2
1 1 4
输出:
8
java代码:
import java.util.Arrays;
import java.util.Scanner;
public class Q5 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
int prices[] = new int[n];
for (int i = 0; i < n; i++) {
prices[i] = sc.nextInt();
}
long dp[][] = new long[n][n];//dp[i][j] 表示在第i天拥有j注股票的最大资产 ,n天最多n-1支股票
Arrays.fill(dp[0], -1);
dp[0][0] = m;//第0天 0注股票拥有m元
if (m >= prices[0]) {
dp[0][1] = m - 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) {
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) {
if (dp[i - 1][j + 1] != -1) {
dp[i][j] = Math.max(dp[i][j], dp[i - 1][j + 1] + prices[i]);
}
}
}
}
long ans = 0;
for (int i = 0; i < n; i++) {
if (dp[n - 1][i] == -1) continue;
ans = Math.max(ans, dp[n - 1][i] + i * prices[n - 1]);
}
// print(dp);
System.out.println(ans);
}
public static void print(int dp[][]) {
int n = dp.length;
System.out.print("\t\t");
for (int i = 0; i < n; i++) {
System.out.print("d" + i + "\t");
}
System.out.println();
for (int i = 0; i < n; i++) {
System.out.print(i + "注股票\t");
for (int j = 0; j < n; j++) {
System.out.print(dp[j][i] + "\t");
}
System.out.println();
}
}
}