网易2018届校招笔试-编程题

参加了网易校招笔试,做编程题的时候可能是太紧张了,没有做的很好,所以事后又分析了一遍,现在整理一下做题的思路及解题过程。



1、魔术币

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

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


输出描述:
输出一个字符串,每个字符表示该次小易选取投入的魔法机器。其中只包含字符'1'和'2'。
思路分析:由题可知,机器1可产生奇数个魔术币,机器2 可产生偶数个魔术币,每次都把全部魔术币投入


#python3
n=int(input())
res=[]
while(n>0):
    if n%2==1:
        res.append('1')
        n=(n-1)/2
    else:
        res.append('2')
        n=(n-2)/2
res.reverse()
print(''.join(res))


如果需要循环输入,可以用while

# Author : yimi
while True:
    try:
        n=int(input())
        res=[]
        while(n>0):
            if n%2==1:
                res.append('1')
                n=(n-1)/2
            else:
                res.append('2')
                n=(n-2)/2
        res.reverse()
        print(''.join(res))
    except:
        break



2、相反数

为了得到一个数的"相反数",我们将这个数的数字顺序颠倒,然后再加上原先的数得到"相反数"。例如,为了得到1325的"相反数",首先我们将该数的数字顺序颠倒,我们得到5231,之后再加上原先的数,我们得到5231+1325=6556.如果颠倒之后的数字有前缀零,前缀零将会被忽略。例如n = 100, 颠倒之后是1. 

输入描述:
输入包括一个整数n,(1 ≤ n ≤ 10^5)


输出描述:
输出一个整数,表示n的相反数

输入例子1:
1325

输出例子1:
6556
思路分析:这个就是两个数相加,相反数可以想到列表的反转reverse,所以考虑用列表解题

# Author : yimi

while True:
    try:
        n=raw_input()
        m=n[::-1]
        print int(n)+int(m)
    except:
        break


3、字符串碎片

一个由小写字母组成的字符串可以看成一些同一字母的最大碎片组成的。例如,"aaabbaaac"是由下面碎片组成的:'aaa','bb','c'。牛牛现在给定一个字符串,请你帮助计算这个字符串的所有碎片的平均长度是多少。

输入描述:
输入包括一个字符串s,字符串s的长度length(1 ≤ length ≤ 50),s只含小写字母('a'-'z')


输出描述:
输出一个整数,表示所有碎片的平均长度,四舍五入保留两位小数。

如样例所示: s = "aaabbaaac"
所有碎片的平均长度 = (3 + 2 + 3 + 1) / 4 = 2.25

输入例子1:
aaabbaaac

输出例子1:
2.25

思路分析:字符串长度除以碎片的数量

# Author : yimi

while True:
    try:
        a=raw_input()
        l=len(a)
        s=[]
        count=1
        for i in xrange(len(a)-1):
            if a[i]==a[i+1]:
                count +=1
            else:
                s.append(count)
                count = 1
        s.append(count)
        result=float(sum(s))/int(len(s))
        print '%.2f'%result
    except:
        break


4、游历魔法王国

魔法王国一共有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 2
0 1 2 3

输出例子1:
3

思路分析:贪心算法

#include<iostream>  
#include<vector>  
#include<algorithm>  
using namespace std;  
  
void traversal(int n,int L,vector<int> &parent){  
    int maxlen=0;  
    vector<int> dp(n);  
    for(int i=0;i<n-1;i++){  
        dp[i+1]=dp[parent[i]]+1;  
        maxlen=max(maxlen,dp[i+1]);   //使用贪心算法计算最长链的长度  
    }   
    int validpath=min(maxlen,L);  
    cout<<min(n,1+validpath+(L-validpath)/2);      
}  
int main(){  
    int n,L;  
    cin>>n>>L;  
    vector<int> parent;  
    for(int i=0;i<n-1;i++){  
        int temp;  
        cin>>temp;  
        parent.push_back(temp);  
    }  
    traversal(n,L,parent);  
    return 0;  
}



5、重排数列

小易有一个长度为N的正整数数列A = {A[1], A[2], A[3]..., A[N]}。
牛博士给小易出了一个难题:
对数列A进行重新排列,使数列A满足所有的A[i] * A[i + 1](1 ≤ i ≤ N - 1)都是4的倍数。
小易现在需要判断一个数列是否可以重排之后满足牛博士的要求。 

输入描述:
输入的第一行为数列的个数t(1 ≤ t ≤ 10),
接下来每两行描述一个数列A,第一行为数列长度n(1 ≤ n ≤ 10^5)
第二行为n个正整数A[i](1 ≤ A[i] ≤ 10^9)


输出描述:
对于每个数列输出一行表示是否可以满足牛博士要求,如果可以输出Yes,否则输出No。

输入例子1:
2
3
1 10 100
4
1 2 3 4

输出例子1:
Yes
No

# Author : yimi

a = input()
for i in range(a):
    s_4 = 0
    s_2 = 0
    x_1 = input()
    x = raw_input().split()
    for m in x:
        if int(m) % 4 == 0:
            s_4 += 1
        elif int(m) % 2 == 0:
            s_2 += 1
    if s_2 == 0:
        if len(x)-s_4 <= s_4+1:
            print 'Yes'
        else:
            print 'No'
    else:
        if len(x)-s_4-s_2+1 <= s_4+1:
            print 'Yes'
        else:
            print 'No'



6、最长公共子序列

一个合法的括号匹配序列被定义为:
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:
(())()

输出例子1:
3
import java.util.*;
public class Main{
    public static void main(String[]args){
        Scanner in=new Scanner(System.in);
        String s=in.nextLine();
        System.out.println(work(s));
    }
    public static int work(String s){
        Set<String> set=new HashSet<String>();
        int len=s.length();
        for(int i=0;i<len;i++){
            StringBuilder st=new StringBuilder();
            st.append(s.substring(0,i));
            st.append(s.substring(i+1));
            for(int j=0;j<len-1;j++){
                StringBuilder sw=new StringBuilder();
                sw.append(st.substring(0, j));
                sw.append(s.charAt(i));
                sw.append(st.substring(j));
                if(legal(sw.toString()))
                    set.add(sw.toString());
            }
        }
        return set.size()-1;
    }
    public static boolean legal(String s){
        int count=0;
        for(int i=0;i<s.length();i++)
        {
            if(s.charAt(i)=='(')
                count++;
            else
                count--;
            if(count<0)
                return false;
        }


        return count==0;
    }
}


7、合唱

小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:
5
1 5 6 2 1

输出例子1:
3
package niuke;

import java.util.Scanner;
public class hechang {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while (in.hasNext()) {
            int len = in.nextInt();
            int[] arr = new int[len];
            for (int i = 0; i < len; ++i) {
                arr[i] = in.nextInt();
            }
            if (len < 3) {
                System.out.println("0");
            } else {
                int[][] dp = new int[len][len];
                int[] acc = new int[len];
                dp[0][0] = 0 - Math.abs(arr[1] - arr[0]);
                for (int i = 1; i < len; ++i) {
                    acc[i] = acc[i - 1] + Math.abs(arr[i] - arr[i - 1]);
                    dp[i][i - 1] = acc[i - 1];
                    for (int j = 0; j < i - 1; ++j) {
                        dp[i][j] = dp[i - 1][j] + acc[i] - acc[i - 1];
                        dp[i][i - 1] = Math.min(dp[i][i - 1], dp[i - 1][j] + Math.abs(arr[i] - arr[j]));
                    }
                }
                int min = Integer.MAX_VALUE;
                for (int j = 0; j < len - 1; ++j) {
                    min = Math.min(min, dp[len - 1][j]);
                }
                System.out.println(min);
            }
        }
    }
}

8、射击游戏

小易正在玩一款新出的射击游戏,这个射击游戏在一个二维平面进行,小易在坐标原点(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:
5
0 -1 1 1 -1
0 -1 -1 1 1

输出例子1:
5

import java.util.Scanner;
  
public class Main {
  
    public static int max(int a, int b) {
        return (a > b) ? a : b;
    }
  
    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);
  
        int[] x = new int[100];
        int[] y = new int[100];
        int n;
        n = cin.nextInt();
        for (int i = 0; i < n; i++) {
            x[i] = cin.nextInt();
        }
        for (int i = 0; i < n; i++) {
            y[i] = cin.nextInt();
        }
  
        if (n <= 2) {
            System.out.println(n);
            return;
        }
        int res = 1;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (i != j) {
                    int dx1 = x[j] - x[i];
                    int dy1 = y[j] - y[i];
                    for (int k = 0; k < n; k++) {
                        int cnt = 0;
                        if (i != k && j != k) {
                            for (int r = 0; r < n; r++) {
                                int dx2 = x[r] - x[i];
                                int dy2 = y[r] - y[i];
                                if (dy1 * dx2 == dy2 * dx1) {
                                    cnt++;
                                } else {
                                    dx2 = x[r] - x[k];
                                    dy2 = y[r] - y[k];
                                    if (dy1 * dy2 == -dx2 * dx1) {
                                        cnt++;
                                    }
                                }
                            }
                        }
                        res = max(res, cnt);
                    }
                }
            }
        }
        System.out.println(res);
  
  
    }
}





  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值