腾讯0424开发岗笔试题代码
第一题
给n个数字字符串,每个字符串长度为m,然后从上到下对齐,从上到下构建数字,排序输出。
思路:暴力
import java.io.BufferedInputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;
public class Q1 {
public static void main(String[] args) {
Scanner sc = new Scanner(new BufferedInputStream(System.in));
int n = sc.nextInt();
String strs[] = new String[n];
sc.nextLine();
for (int i = 0; i < n; i++) {
strs[i] = sc.nextLine();
}
int m = strs[0].length();
List<Integer> nums = new ArrayList();
for (int i = 0; i < m; i++) {
int num = 0;
for (int j = 0; j < n; j++) {
num = num * 10 + (strs[j].charAt(i)-'0');
}
nums.add(num);
}
nums.sort((o1,o2)->{return o1-o2;});
for (int i = 0; i < nums.size(); i++) {
System.out.print(nums.get(i)+" ");
}
}
}
第二题
给一个数组,下标从1-n,每次淘汰下标非质数的数字,然后重新组成数组,问最后剩下的数字为何数?
思路:暴力
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;
}
}
第三题
给一堆字符串代表一排士兵,士兵编号1~n,字符串中‘0’的士兵代表进攻性的,‘1’的代表防御性的,每个士兵的攻击力或守备力为其下标值。将士兵分组,0~pos的是进攻组,只算攻击力,pos+1~n的是防御组,只算防御力。pos可以取0~n。求攻击组的攻击力和防御组的防御力的差的绝对值的最小值。
思路:使用前缀和记录攻击力和防御力,并逐一求差值的绝对值的最小值。
import java.util.Scanner;
public class Q3 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
sc.nextLine();
String str = sc.nextLine();
long attack[] = new long[n + 1];
long defend[] = new long[n + 1];
for (int i = 1; i <= n; i++) {
attack[i] = attack[i - 1];
defend[i] = defend[i - 1];
//只会进攻
if (str.charAt(i - 1) == '0') {
attack[i] += i;
} else {
//只会防守
defend[i] += i;
}
// System.out.println(i + "\t前缀和进攻值:" + attack[i]);
// System.out.println(i + "\t前缀和防御值:" + attack[i]);
}
//1-pos是进攻的 为1的 pos+1到n是防守
//考虑全进攻和全防守的形式
long ans = Math.min(attack[n], defend[n]);
// System.out.println("全进攻:" + attack[n]);
// System.out.println("全防守:" + defend[n]);
for (int i = 1; i < n; i++) {
// System.out.println("坐标:\t" + i);
// System.out.println("\t\t进攻值:" + attack[i] + "\t防御值:" +(defend[n]-defend[i]));
// System.out.println("\t\t绝对值:" + Math.abs(attack[i] - (defend[n]-defend[i])));
ans = Math.min(ans, Math.abs(attack[i] - (defend[n]-defend[i])));
}
System.out.println(ans);
}
}
第四题
给一个链表数组,数组中的每个链表是一个循环链表中的破碎的部分,且每个链表结点的值唯一且为数值类型,求将这个循环链表复原以后,从链表中任意一个结点正序或逆序遍历 字典序 最小的那个链表,并返回。
思路:链表中结点的值唯一,使用字典记录结点的前驱和后继,并记录最小值,然后从最小值开始遍历,并判断最小值的前驱和后继哪个更小,从更小的开始顺序遍历。
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("}");
}
} 第五题
股票问题,一开始有初始资金m,和一个长度为n的股票价格数组,每天可以进行买入股票或者卖出股票其中的一种操作,或不操作。可以同时持有多个股票,问最后一天的最大总资产是多少?(最大总资产为持有现金+持有的股票价格) 思路:动态规划,设dp[i][j]为第i天持有j个股票能拥有的最大现金额度,dp[i][j] = Math.min(dp[i-1][j] , dp[i][j+1] +prices[i] , dp[i][j-1]-prices[i])
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();
}
}
}
顺丰集团工作强度 374人发布