获得最多的奖金
题目描述
小明在越南旅游,参加了当地的娱乐活动。小明运气很好,拿到了大奖, 到了最后的拿奖金环节。小明发现桌子上放着一列红包,每个红包上写着奖金数额。
现在主持人给要求小明在这一列红包之间“切”2刀,将这一列红包“切”成3组,并且第一组的奖金之和等于最后一组奖金和(允许任意一组的红包集合是空)。最终第一组红包的奖金之和就是小明能拿到的总奖金。小明想知道最多能拿到的奖金是多少,你能帮他算算吗。
举例解释:桌子上放了红包 1, 2, 3, 4, 7, 10。小明在“4,7”之间、“7,10” 之间各切一刀,将红包分成3组 [1, 2, 3, 4] [7] [10],其中第一组奖金之和=第三组奖金之和=10,所以小明可以拿到10越南盾。
输入描述:
第一行包含一个正整数n,(1<=n<= 200 000),表示有多少个红包。
第二行包含n个正整数d[i],表示每个红包包含的奖金数额。其中1<= d[i] <= 1000 000 000
输出描述:
小明可以拿到的总奖金
示例1
输入
5
1 3 1 1 4
输出
5
说明
[1,3,1] [ ] [1,4] ,其中第一组奖金和是5,等于第三组奖金和。所以小明可以拿到5越南盾
示例2
输入
5
1 3 2 1 4
输出
4
说明
[1,3] [2,1] [4],小明可以拿到4越南盾
示例3
输入
3
4 1 2
输出
0
说明
[ ] [4, 1, 2] [ ] ,小明没办法,为了保证第一组第三组相等,只能都分成空的。所以小明只能拿到0越南盾。
import java.util.*;
public class Main {
//贪心法,从两边向中间移动,更新maxSum
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
while(input.hasNextInt()) {
int n = input.nextInt();
int[] nums = new int[n];
for(int i = 0; i < n; i++) {
nums[i] = input.nextInt();
}
long maxSum = 0, leftSum = 0, rightSum = 0;
int i = -1, j = nums.length;
//j-1==1时第二组为空,不需要再试了
//用++i和--j使while判断时每个i和j都是已经加过的
while(j - i > 1) {
if(leftSum <= rightSum) {
leftSum += nums[++i];
}
else {
rightSum += nums[--j];
}
if(leftSum == rightSum) {
maxSum = leftSum;
}
}
System.out.println(maxSum);
}
input.close();
}
}
将满二叉树转换为求和树
二叉树:
10
/ \
-2 6
/ \ / \
8 -4 7 5
求和树:
20(4-2+12+6)
/ \
4(8-4) 12(7+5)
/ \ / \
0 0 0 0
二叉树给出前序和中序输入,求和树要求中序输出;
所有处理数据不会大于int;
下面代码只通过60%,暂时还没找出原因
import java.util.*;
public class Main {
//利用满二叉树的特性,最小子树节点为3个时为递归出口
public static void sumTree(int[] in, int inStart, int inEnd) {
//3个节点的树,递归出口
if(inEnd - inStart == 2) {
in[inStart + 1] = in[inStart] + in[inStart + 2];
in[inStart] = 0;
in[inStart + 2] = 0;
return;
}
//否则遍历完左右子树,再求根节点
//防溢出写法
int root = inStart + (inEnd - inStart) / 2;
int left = inStart + (root - 1 - inStart) / 2;
int right = root + 1 + (inEnd - root - 1) / 2;
//遍历之前就要改掉根节点
in[root] = in[left] + in[right];
sumTree(in, inStart, root - 1);
sumTree(in, root + 1, inEnd);
in[root] += in[left] + in[right];
}
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
while(input.hasNextInt()) {
String[] sArr = input.nextLine().split(" ");
int n = sArr.length;
int[] pre = new int[n], in = new int[n];
for(int i = 0; i < n; i++) {
pre[i] = Integer.valueOf(sArr[i]);
}
for(int i = 0; i < n; i++) {
in[i] = input.nextInt();
}
//将n>=3开始的交给函数处理
if(n == 1) {
System.out.println(in[0]);
continue;
}
sumTree(in, 0, n - 1);
for(int num : in) {
System.out.print(num + " ");
}
System.out.println("");
}
input.close();
}
}
求表达式 f(n)结果末尾0的个数
时间限制:1秒
空间限制:32768K
输入一个自然数n,求表达式 f(n) = 1!2!3!.....n! 的结果末尾有几个连续的0?
输入描述:
自然数n
输出描述:
f(n)末尾连续的0的个数
输入例子1:
11
输出例子1:
9
import java.util.*;
public class Main {
//单个n!的结尾0个数
public static int countZero(int n) {
int count = 0;
int weight = 5;
while(n / weight != 0) {
count += n / weight;
weight *= 5;
}
return count;
}
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
while(input.hasNextInt()) {
int n = input.nextInt();
int count = 0;
for(int i = 1; i <= n; i++) {
count += countZero(i);
}
System.out.println(count);
}
input.close();
}
}
幼儿园分班
幼儿园一个大班要分成两个小班,有些小朋友不希望自己和其他某几位小朋友同班。园长向大家收集了不希望同班的要求,然后视情况将一个大班的小朋友分成两个班。请你开发一个程序,帮助园长快速判断是否所有小朋友的不同班请求都可以被满足。
输入描述:
输入分为三部分,第一个部分是一个 int,代表这个大班里小朋友的总数。第二部分是一个 int,代表园长采集到的小朋友们的请求数。第三部分是小朋友们的请求,每个请求由两个 int 组成,第一个 int 代表提请求的小朋友,第二个 int 代表他不希望同班的另一位小朋友。
输出描述:
如果所有小朋友的请求都可以被满足,输出 1,否则输出 0。
输入例子1:
5
5
1 2
1 3
1 4
1 5
2 3
输出例子1:
0
例子说明1:
总共有 5 位小朋友,总共采集到了 5 个请求。分别是:1 不希望和 2 同班。1 不希望和 3 同班。1 不希望和 4 同班。1 不希望和 5 同班。2 不希望和 3 同班。不能满足所有人的请求,输出 0。
输入例子2:
5
4
1 2
1 3
1 4
1 5
输出例子2:
1
例子说明2:
总共有 5 位小朋友,总共采集到了 4 个请求。分别是:1 不希望和 2 同班。1 不希望和 3 同班。1 不希望和 4 同班。1 不希望和 5 同班。可以满足所有人的请求,分班方式:1 一个人一班,2、3、4、5 另一班。输出 1。
import java.util.*;
public class Main {
//遍历两次所有请求,如果第二次遍历发现仍需调整,说明无法满足
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
while(input.hasNextInt()) {
int n = input.nextInt();
//用两个set代表两个班
HashSet<Integer> set1 = new HashSet<Integer>();
HashSet<Integer> set2 = new HashSet<Integer>();
for(int i = 1; i <= n; i++) {
set1.add(i);
}
int n2 = input.nextInt();
int[][] request = new int[n2][2];
for(int i = 0; i < n2; i++) {
request[i][0] = input.nextInt();
request[i][1] = input.nextInt();
if(set1.contains(request[i][0]) && set1.contains(request[i][1])) {
set1.remove(request[i][1]);
set2.add(request[i][1]);
}
else if(set2.contains(request[i][0]) && set2.contains(request[i][1])) {
set2.remove(request[i][1]);
set1.add(request[i][1]);
}
}
int i = 0;
for(; i < n2; i++) {
//分班失败
if(set1.contains(request[i][0]) && set1.contains(request[i][1])
|| set2.contains(request[i][0]) && set2.contains(request[i][1])) {
System.out.println("0");
break;
}
}
//成功分班
if(i == n2) {
System.out.println("1");
}
}
}
}
小米第一题,括号构建二叉树,输出中序遍历
例:1(2(3,4(,5)),6(7,)) 输出:3245176
import java.io.*;
import java.util.*;
public class Main {
static class TreeNode {
String val;
TreeNode left;
TreeNode right;
public TreeNode(String val) {
this.val = new String(val);
}
}
static String solution(String input) {
if(input == null) {
return null;
}
TreeNode root = generateTree(input);
StringBuilder res = new StringBuilder();
inOrder(root, res);
return res.toString();
}
static TreeNode generateTree(String input) {
if(input.equals("")) {
return null;
}
while (input.startsWith("(")) {
input = input.substring(1, input.length() - 1);
}
if(input.indexOf('(') < 0) {
return new TreeNode(input);
}
int leftStart = input.indexOf('(') + 1;
int leftEnd = leftStart;
TreeNode root = new TreeNode(input.substring(0, leftStart - 1));
int count = 0;
for(int i = leftStart; i < input.length() - 1; i++) {
if(input.charAt(i) == ',' && count == 0) {
leftEnd = i;
break;
}
else if(input.charAt(i) == '(') {
count++;
}
else if(input.charAt(i) == ')') {
count--;
}
}
root.left = generateTree(input.substring(leftStart, leftEnd));
root.right = generateTree(input.substring(leftEnd + 1, input.length() - 1));
return root;
}
static void inOrder(TreeNode root, StringBuilder res) {
if(root == null) {
return;
}
inOrder(root.left, res);
res.append(root.val);
inOrder(root.right, res);
}
}
网易互娱第二批笔试
1.二进制回文数
import java.util.Scanner;
public class Main {
public static boolean isPandNum(int num) {
if((num & 1) == 0) {
return false;
}
int i = 30;
for(; i >= 0; i--) {
if(((num >> i) & 1) > 0) {
break;
}
}
int j = 0;
while(i > j) {
if(((num >> i) & 1) != ((num >> j) & 1)) {
return false;
}
else {
i--;
j++;
}
}
return true;
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while(in.hasNextInt()) {
int t = in.nextInt();
boolean[] res = new boolean[t];
for(int i = 0; i < t; i++) {
res[i] = isPandNum(in.nextInt());
}
for(int i = 0; i < t; i++) {
if(res[i]) {
System.out.println("YES");
}
else {
System.out.println("NO");
}
}
}
}
}
2.按编号顺序给定树节点val、left编号、right编号,,1为null,每行3个值,输出是否是递增树,即每层val之和严格递增
import java.util.ArrayList;
import java.util.Scanner;
public class Main {
public static class TreeNode {
public int val;
public TreeNode left;
public TreeNode right;
public boolean isRoot = true;
}
public static boolean increTree(TreeNode root) {
ArrayList<Integer> sums = new ArrayList<>();
preOrder(root, 0, sums);
for(int i = 1; i < sums.size(); i++) {
if(sums.get(i) <= sums.get(i - 1)) {
return false;
}
}
return true;
}
public static void preOrder(TreeNode root, int depth, ArrayList<Integer> sums) {
if(root == null) {
return;
}
if(sums.size() == depth) {
sums.add(root.val);
}
else {
sums.set(depth, sums.get(depth) + root.val);
}
preOrder(root.left, depth + 1, sums);
preOrder(root.right, depth + 1, sums);
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while(in.hasNextInt()) {
int t = in.nextInt();
boolean[] res = new boolean[t];
for(int i = 0; i < t; i++) {
int n = in.nextInt();
TreeNode[] arr = new TreeNode[n];
for(int j = 0; j < n; j++) {
arr[j] = new TreeNode();
}
for(int j = 0; j < n; j++) {
arr[j].val = in.nextInt();
int left = in.nextInt();
int right = in.nextInt();
if(left != -1) {
arr[j].left = arr[left];
arr[left].isRoot = false;
}
if(right != -1) {
arr[j].right = arr[right];
arr[right].isRoot = false;
}
}
for(int j = 0; j < n; j++) {
if(arr[j].isRoot) {
res[i] = increTree(arr[j]);
break;
}
}
}
for(int i = 0; i < t; i++) {
if(res[i]) {
System.out.println("YES");
}
else {
System.out.println("NO");
}
}
}
}
}
3.一个月30天,给定连续两天喝咖啡的最小间隔天数k,以及m个确定会喝的天,求最多喝多少天(在k和m个给定值的限制下最多再插入多少天,再加上m)
import java.util.Scanner;
public class Main {
public static int maxInsert(int a, int b, int k) {
if(a == 0) {
return (b - k - 1 + k) / (1 + k);
}
if(b == 31) {
return (30 - a - k + k) / (1 + k);
}
int count = 0;
for(int i = a + k + 1; i < b - k; i += k + 1) {
count++;
}
return count;
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while(in.hasNextInt()) {
int t = in.nextInt();
int[] res = new int[t];
for(int i = 0; i < t; i++) {
int k = in.nextInt();
int m = in.nextInt();
if(m == 0) {
res[i] = (30 + k) / (1 + k);
continue;
}
res[i] = m;
int a = 0, b = 0;
for(int j = 0; j < m; j++) {
b = in.nextInt();
res[i] += maxInsert(a, b, k);
a = b;
}
res[i] += maxInsert(b, 31, k);
}
for(int i = 0; i < t; i++) {
System.out.println(res[i]);
}
}
}
}
4.给定01矩阵,求最大十字旗左上和右下坐标同样大的取最左上(十字旗:3x3一共9个正方形,24568为全1,其余全0)
VIVO 9.11笔试
2.二维01背包
给定一台服务器磁盘和内存大小,以及一组程序,每个程序已知需要的磁盘和内存、用户数,每个程序只能部署一次,求最大可得的用户数
import java.io.*;
import java.util.*;
/**
* Welcome to vivo !
*/
public class Main {
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String inputStr = br.readLine();
String[] input = inputStr.split(" ");
int totalDisk = Integer.parseInt(input[0]);
int totalMemory = Integer.parseInt(input[1]);
List<Service> services = parseServices(input[2].split("#"));
int output = solution(totalDisk, totalMemory, services);
System.out.println(output);
}
private static int solution(int totalDisk, int totalMemory, List<Service> services) {
// TODO Write your code here
int n = services.size();
int[][][] dp = new int[n + 1][totalDisk + 1][totalMemory + 1];
for(int i = 1; i <= n; i++ ) {
for(int j = 1; j <= totalDisk; j++) {
for (int k = 1; k <= totalMemory; k++) {
if(services.get(i - 1).disk > j || services.get(i - 1).memory > k) {
dp[i][j][k] = dp[i - 1][j][k];
}
else {
dp[i][j][k] = Math.max(dp[i - 1][j][k], dp[i - 1][j - services.get(i - 1).disk][k - services.get(i - 1).memory] + services.get(i - 1).users);
}
}
}
}
return dp[n][totalDisk][totalMemory];
}
private static List<Service> parseServices(String[] strArr) {
if (strArr == null || strArr.length == 0) {
return new ArrayList<Service>(0);
}
List<Service> services = new ArrayList<>(strArr.length);
for (int i = 0; i < strArr.length; i++) {
String[] serviceArr = strArr[i].split(",");
int disk = Integer.parseInt(serviceArr[0]);
int memory = Integer.parseInt(serviceArr[1]);
int users = Integer.parseInt(serviceArr[2]);
services.add(new Service(disk, memory, users));
}
return services;
}
static class Service {
private int disk;
private int memory;
private int users;
public Service(int disk, int memory, int users) {
this.disk = disk;
this.memory = memory;
this.users = users;
}
public int getDisk() {
return disk;
}
public void setDisk(int disk) {
this.disk = disk;
}
public int getMemory() {
return memory;
}
public void setMemory(int memory) {
this.memory = memory;
}
public int getusers() {
return users;
}
public void setusers(int users) {
this.users = users;
}
}
}
58集团9.13笔试
2. 发饼干,输入数组代表每个小朋友的分数,要求每个人和相邻左右两个的分数比较,相邻分数低的饼干数要少于分数高的;
没人至少发一个饼干,求最少要准备多少个饼干
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while(in.hasNext()) {
int n = in.nextInt();
int[] scores = new int[n];
for(int i = 0; i < n; i++) {
scores[i] = in.nextInt();
}
int[] cakes = new int[n];
//初始化全1
Arrays.fill(cakes, 1);
for(int i = 1; i < n; i++) {
//每个位置默认前面是最优解,则当前位置比前一个大的时候+1
if(scores[i] > scores[i - 1]) {
cakes[i] = cakes[i - 1] + 1;
}
//否则当前位置比前一个小的时候,只有前一个为1时需要处理(前一个不为1时当前默认1即可)
else if(cakes[i - 1] == 1) {
for(int j = i - 1; j >= 0; j--) {
if(scores[j] > scores[j + 1] && cakes[j] <= cakes[j + 1]) {
cakes[j] = cakes[j + 1] + 1;
//System.out.println("cakes " + i + " = " + cakes[i]);
}
if(j > 0 && scores[j] < scores[j - 1] && cakes[j] < cakes[j - 1]) {
break;
}
}
}
}
int sum = 0;
for(int num : cakes) {
sum += num;
}
System.out.print(sum);
}
}
}
3.输入矩阵权值,求左上到右下最小权值路径。(简单动态规划)
import java.util.Scanner;
public class Main3 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (in.hasNext()) {
int m = in.nextInt(), n = in.nextInt();
int[][] weights = new int[m][n];
for(int i = 0; i < m; i++) {
for(int j = 0; j < n; j++) {
weights[i][j] = in.nextInt();
if(i == 0 && j == 0) {
continue;
}
else if(i == 0) {
weights[0][j] += weights[0][j - 1];
}
else if(j == 0) {
weights[i][0] += weights[i - 1][0];
}
else {
weights[i][j] += Math.min(weights[i - 1][j], weights[i][j - 1]);
}
}
}
System.out.print(weights[m - 1][n - 1]);
}
}
}
VipKid 9.16笔试第2题,整数拆分成多个数之和,输出所有结果
例如输入:
4
输出:
1+1+1+1
1+1+2
1+3
2+2
4
import java.util.Arrays;
import java.util.Scanner;
public class Main2 {
public static String fun(int t) {
StringBuilder res = new StringBuilder();
int[] arr = new int[t];
Arrays.fill(arr, 1);
int sum = t;
int index = t - 1;
while(arr[0] != 0) {
if(sum == t) {
for(int j = 0; j < index; j++) {
res.append(arr[j] + "+");
}
res.append(arr[index] + "\n");
sum -= arr[index];
arr[index] = 0;
index--;
if(index >= 0) {
arr[index]++;
sum++;
}
continue;
}
if(sum < t) {
arr[index + 1] = arr[index];
sum += arr[index + 1];
index++;
continue;
}
else {
sum -= arr[index];
if(index - 1 >= 0) {
arr[index - 1]++;
sum++;
}
index--;
}
}
return res.toString();
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while(in.hasNext()) {
int t = in.nextInt();
System.out.print(fun(t));
}
}
}
9.21 网易笔试
3. 最大和上升子序列(每个元素 >= 前面所有元素的和)
写完感觉逻辑没问题,不知道为什么一直0%
import java.util.Scanner;
public class Main {
public static int fun(long[] nums, int n) {
int[] dp = new int[n];
long[] sum = new long[n];
dp[0] = 1;
sum[0] = nums[0];
int max = 1;
for(int i = 1; i < n; i++) {
dp[i] = 1;
sum[i] = nums[i];
for(int j = 0; j < i; j++) {
if(sum[j] <= nums[i]) {
if(dp[j] + 1 > dp[i]) {
dp[i] = dp[j] + 1;
sum[i] = sum[j] + nums[i];
}
else if(dp[j] + 1 == dp[i] && sum[i] > sum[j] + nums[i]) {
sum[i] = sum[j] + nums[i];
}
}
}
max = Math.max(max, dp[i]);
}
return max;
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (in.hasNext()) {
int t = in.nextInt();
int[] res = new int[t];
for (int i = 0; i < t; i++) {
int n = in.nextInt();
if(n == 0) {
res[i] = 0;
continue;
}
long[] nums = new long[n];
for (int j = 0; j < n; j++) {
nums[j] = (long) in.nextInt();
}
res[i] = fun(nums, n);
}
for (int i = 0; i < t; i++) {
System.out.println(res[i]);
}
}
}
}
4. 求1-n的乱序数组逆序距离和
没想到最优解法,只会暴力
import java.util.Scanner;
public class Main4 {
public static int fun(int[] nums, int n) {
int sum = 0;
for (int i = 1; i < n; i++) {
for (int j = i - 1; j >= 0; j--) {
if(nums[j] > nums[i]) {
sum += nums[j] - nums[i];
}
}
}
return sum;
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (in.hasNext()) {
int n = in.nextInt();
int[] nums = new int[n];
for(int i = 0; i < n; i++) {
nums[i] = in.nextInt();
}
System.out.println(fun(nums, n));
}
}
}