2017 网易校招

来源:互联网 发布:淘宝链接里的花店地址 编辑:程序博客网 时间:2024/05/17 01:07

小易准备去魔法王国采购魔法神器,购买魔法神器需要使用魔法币,但是小易现在一枚魔法币都没有,但是小易有两台魔法机器可以通过投入x(x可以为0)个魔法币产生更多的魔法币。
魔法机器1:如果投入x个魔法币,魔法机器会将其变为2x+1个魔法币
魔法机器2:如果投入x个魔法币,魔法机器会将其变为2x+2个魔法币
小易采购魔法神器总共需要n个魔法币,所以小易只能通过两台魔法机器产生恰好n个魔法币,小易需要你帮他设计一个投入方案使他最后恰好拥有n个魔法币。 

输入描述:
输入包括一行,包括一个正整数n(1 ≤ n ≤ 10^9),表示小易需要的魔法币数量。


输出描述:
输出一个字符串,每个字符表示该次小易选取投入的魔法机器。其中只包含字符'1'和'2'。

输入例子1:
10

输出例子1:
122

思路:从后往前推




魔法王国一共有n个城市,编号为0~n-1号,n个城市之间的道路连接起来恰好构成一棵树。
小易现在在0号城市,每次行动小易会从当前所在的城市走到与其相邻的一个城市,小易最多能行动L次。
如果小易到达过某个城市就视为小易游历过这个城市了,小易现在要制定好的旅游计划使他能游历最多的城市,请你帮他计算一下他最多能游历过多少个城市(注意0号城市已经游历了,游历过的城市不重复计算)。 

输入描述:
输入包括两行,第一行包括两个正整数n(2 ≤ n ≤ 50)和L(1 ≤ L ≤ 100),表示城市个数和小易能行动的次数。第二行包括n-1个整数parent[i](0 ≤ parent[i] ≤ i), 对于每个合法的i(0 ≤ i ≤ n - 2),在(i+1)号城市和parent[i]间有一条道路连接。


输出描述:
输出一个整数,表示小易最多能游历的城市数量。

输入例子1:
5 20 1 2 3

输出例子1:
3

思路:先走最长的路径(树的最大深度)
 * 剩下城市到达一次需要2步
 * 这个思路想到了,但是没有继续深入想下去,汗、。。。猜了后直接带例子也可以确认自己的想法对不对啊。。。
 */

package l4;import java.util.Scanner;/* * 有3个point * 1. 树 * 2. parent[i] ≤ i * 3. 0一定是root,每个分支都是数组以0分界 *  * 先走最长的路径(树的最大深度) * 剩下城市到达一次需要2步 * 这个思路想到了,但是没有继续深入想下去,汗、。。。猜了后直接带例子也可以确认自己的想法对不对啊。。。 */public class Main {public static void main(String[] args) {Scanner sc = new Scanner(System.in);int n = sc.nextInt(), m = sc.nextInt();int[] depth = new int[n];int maxDepth = 0;for(int i=1; i<n; i++) {int t = sc.nextInt();depth[i] = depth[t] + 1;maxDepth = Math.max(maxDepth, depth[i]);}if(maxDepth >= m)System.out.println(m+1);else {int leftCanGoCity = (m-maxDepth)/2;int all = leftCanGoCity + maxDepth + 1;System.out.println(Math.min(all, n));}}}



小Q和牛博士合唱一首歌曲,这首歌曲由n个音调组成,每个音调由一个正整数表示。
对于每个音调要么由小Q演唱要么由牛博士演唱,对于一系列音调演唱的难度等于所有相邻音调变化幅度之和, 例如一个音调序列是8, 8, 13, 12, 那么它的难度等于|8 - 8| + |13 - 8| + |12 - 13| = 6(其中||表示绝对值)。
现在要对把这n个音调分配给小Q或牛博士,让他们演唱的难度之和最小,请你算算最小的难度和是多少。
如样例所示: 小Q选择演唱{5, 6}难度为1, 牛博士选择演唱{1, 2, 1}难度为2,难度之和为3,这一个是最小难度和的方案了。 

输入描述:
输入包括两行,第一行一个正整数n(1 ≤ n ≤ 2000) 第二行n个整数v[i](1 ≤ v[i] ≤ 10^6), 表示每个音调。


输出描述:
输出一个整数,表示小Q和牛博士演唱最小的难度和是多少。

输入例子1:
51 5 6 2 1

输出例子1:
3

思路:最开始想DP,dp[i][j]表示到i位置,且i位置的音符有j来唱,但是这样递推不到前面的情况,因为需要知道某个人之前最近是唱的那个音符

写DP遇到难处,先写下递归,试想一下,要倒推到前面的情况,应该用什么来表示当前的状态?

dp[i][j]表示小Q唱到第i个音符,博士唱到第j个音符,(我们自然也知道当前唱到的是max(i,j))

public class TLE {static int[][] memo;public static void main(String[] args) {Scanner sc = new Scanner(System.in);int n = sc.nextInt();int[] a = new int[n];for(int i=0; i<n; i++)a[i]=sc.nextInt();memo = new int[n][n];System.out.println(dp(a, -1, -1));}private static int dp(int[]a, int i, int j) {if(i>=0 && j>=0 && memo[i][j] != 0)return memo[i][j];int next = Math.max(i, j) + 1;if(next == a.length)return 0;int ret = Integer.MAX_VALUE;ret = Math.min(ret, dp(a, next, j) + (i==-1?0:Math.abs(a[next]-a[i])));ret = Math.min(ret, dp(a, i, next) + (j==-1?0:Math.abs(a[next]-a[j])));if(i>=0 && j>=0) memo[i][j] = ret;return ret;}}

根据递归该DP就好了

package l7;import java.util.Scanner;/** * DP */public class Main {public static void main(String[] args) {Scanner sc = new Scanner(System.in);int n = sc.nextInt();int[] a = new int[n];for(int i=0; i<n; i++)a[i]=sc.nextInt();int[][] dp = new int[n+1][n+1];for(int i=n-1; i>=0; i--) {for(int j=n-1; j>=0; j--) {int next = Math.max(i, j) + 1;dp[i][j] = Integer.MAX_VALUE;dp[i][j] = Math.min(dp[i][j], dp[next][j]+(i==0?0:Math.abs(a[next-1]-a[i-1])));dp[i][j] = Math.min(dp[i][j], dp[i][next]+(j==0?0:Math.abs(a[next-1]-a[j-1])));}}System.out.println(dp[0][0]);}}



一个合法的括号匹配序列被定义为:
1. 空串""是合法的括号序列
2. 如果"X"和"Y"是合法的序列,那么"XY"也是一个合法的括号序列
3. 如果"X"是一个合法的序列,那么"(X)"也是一个合法的括号序列
4. 每个合法的括号序列都可以由上面的规则生成
例如"", "()", "()()()", "(()())", "(((()))"都是合法的。
从一个字符串S中移除零个或者多个字符得到的序列称为S的子序列。
例如"abcde"的子序列有"abe","","abcde"等。
定义LCS(S,T)为字符串S和字符串T最长公共子序列的长度,即一个最长的序列W既是S的子序列也是T的子序列的长度。
小易给出一个合法的括号匹配序列s,小易希望你能找出具有以下特征的括号序列t:
1、t跟s不同,但是长度相同
2、t也是一个合法的括号匹配序列
3、LCS(s, t)是满足上述两个条件的t中最大的
因为这样的t可能存在多个,小易需要你计算出满足条件的t有多少个。

如样例所示: s = "(())()",跟字符串s长度相同的合法括号匹配序列有:
"()(())", "((()))", "()()()", "(()())",其中LCS( "(())()", "()(())" )为4,其他三个都为5,所以输出3.

输入描述:
输入包括字符串s(4 ≤ |s| ≤ 50,|s|表示字符串长度),保证s是一个合法的括号匹配序列。


输出描述:
输出一个正整数,满足条件的t的个数。
示例1

输入

(())()

输出

3

思路:直接找出所有valid的字符串,再判断LCS

public class TLE {static List<String> all = new ArrayList<String>();public static void main(String[] args) {Scanner sc = new Scanner(System.in);String s = sc.next();int len = s.length() / 2;char[] cs = new char[2*len];dfs(len, 0, 0, cs, 0);int max = 0, cnt = 0;for(String t : all) {if(s.equals(t))continue;int tmp = getLCS(s, t);if(tmp > max) {max = tmp;cnt = 1;} else if(tmp == max) {cnt ++;}}System.out.println(cnt);}private static int getLCS(String s, String t) {char[] cs1 = s.toCharArray(), cs2 = t.toCharArray();int[][] dp = new int[1+cs1.length][1+cs2.length];for(int i=1; i<=cs1.length; i++){for(int j=1; j<=cs2.length; j++) {if(cs1[i-1] == cs2[j-1])dp[i][j] = dp[i-1][j-1] + 1;elsedp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]);}}return dp[cs1.length][cs2.length];}private static void dfs(int len, int i, int j, char[] cs, int k) {if(k == cs.length) {all.add(new String(cs));return;}if(i<len) {cs[k] = '(';dfs(len, i+1, j, cs, k+1);}if(i>j) {cs[k] = ')';dfs(len, i, j+1, cs, k+1);}}}


换一个角度,先把最大LCS的条件先用掉
 * 当且仅当修改距离为 1 时 LCS 最大

package l6;import java.util.HashSet;import java.util.Scanner;import java.util.Set;/* * 换一个角度,先把最大LCS的条件先用掉 * 当且仅当修改距离为 1 时 LCS 最大 */public class Main {public static void main(String[] args) {Scanner sc = new Scanner(System.in);String s = sc.next();// get all possible max-LCS String using stringbuilderSet<String> set = new HashSet<String>();for(int i=0; i<s.length(); i++) {StringBuilder sb = new StringBuilder(s);char c = sb.charAt(i);sb.deleteCharAt(i);for(int j=0; j<s.length(); j++) {sb.insert(j, c);if(valid(sb.toString()))set.add(sb.toString());sb.deleteCharAt(j);}}System.out.println(set.size()-1);}private static boolean valid(String s) {char[] cs = s.toCharArray();int left = 0;for(char c : cs) {if(c == '(') left++;elseleft--;if(left < 0)return false;}return left == 0;}}


链接:https://www.nowcoder.com/questionTerminal/d3f26db0325444078717cc802e0056d8
来源:牛客网

小易正在玩一款新出的射击游戏,这个射击游戏在一个二维平面进行,小易在坐标原点(0,0),平面上有n只怪物,每个怪物有所在的坐标(x[i], y[i])。小易进行一次射击会把x轴和y轴上(包含坐标原点)的怪物一次性消灭。
小易是这个游戏的VIP玩家,他拥有两项特权操作:
1、让平面内的所有怪物同时向任意同一方向移动任意同一距离
2、让平面内的所有怪物同时对于小易(0,0)旋转任意同一角度
小易要进行一次射击。小易在进行射击前,可以使用这两项特权操作任意次。

小易想知道在他射击的时候最多可以同时消灭多少只怪物,请你帮帮小易。

如样例所示:

所有点对于坐标原点(0,0)顺时针或者逆时针旋转45°,可以让所有点都在坐标轴上,所以5个怪物都可以消灭。

输入描述:
输入包括三行。第一行中有一个正整数n(1 ≤ n ≤ 50),表示平面内的怪物数量。第二行包括n个整数x[i](-1,000,000 ≤ x[i] ≤ 1,000,000),表示每只怪物所在坐标的横坐标,以空格分割。第二行包括n个整数y[i](-1,000,000 ≤ y[i] ≤ 1,000,000),表示每只怪物所在坐标的纵坐标,以空格分割。


输出描述:
输出一个整数表示小易最多能消灭多少只怪物。
示例1

输入

50 -1 1 1 -10 -1 -1 1 1

输出

5
思路:其实就是求2条互相垂直的直线能最多能通过多少点

最开始还想先求出所有的斜率放到Map里面,然后后面再遍历Map,但是存在2条直线相交的点在原来的点之中,

其实这样麻烦的话就直接循环遍历了,反正复杂度都差不多

package l8;import java.util.Scanner;/** * 可以把class A中的List改为截距或者一个点的集合 * 然后每次都要判断,垂直的2条直线相交的点是不是在原来那些点中出现过 *  * 这种近乎暴力的方法绕那么多 * 还不如直接循环 * 前2层循环定出一条直线,第3层循环+斜率定出来一条直线 * 第4层循环判断是否落在这2条直线上 */public class Main {public static void main(String[] args) {Scanner sc = new Scanner(System.in);int n = sc.nextInt();int[] a = new int[n], b = new int[n];for(int i=0; i<n; i++)a[i]=sc.nextInt();for(int i=0; i<n; i++)b[i]=sc.nextInt();if(n < 3) {System.out.println(n);return;}int max = 0;for(int i=0; i<n; i++) {for(int j=i+1; j<n; j++) {double k1 = (b[i]-b[j]) / (a[i]-a[j]+0.0);double b1 = b[i] - k1 * a[i];for(int k=j+1; k<n; k++) {int cnt = 0;for(int l=k+1; l<n; l++) {if(k1*a[l]+b1 == b[l]) {cnt ++;continue;}double k2 = (b[l]-b[k]) / (a[l]-a[k]+0.0);if(k2 * k1 == -1)cnt ++;}max = Math.max(max, cnt);}}}System.out.println(max+3);}}


原创粉丝点击