头条2019.3.16笔试题

这次头条笔试题比之前简单多了。。终于全部过了

  1. 找钱问题,共1024,64,16,4,1几种面值。因为1,4,16,64这几种面值都可以由小于他们的面值凑出来,所以直接贪心的选最大的面值就好。

    import java.util.*;
    
    
    public class Main implements Runnable{
    
        private final int mod = 1000000007, max = 200005;
        private final int [] arr = {64, 16, 4, 1};
    
        public static void main(String[] args) {
            new Thread(null, new Main(), "thread-1", 1024*1024*10).start();
        }
    
        @Override
        public void run() {
            try{
                solve();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    
        private void solve(){
            Scanner cin = new Scanner(System.in);
            int N = 1024-cin.nextInt(), ans = 0;
            for(int i=0; i<4; i++){
                ans += N/arr[i];
                N %= arr[i];
            }
            System.out.println(ans);
        }
    }
    
  2. 简单模拟。去掉三连重复(aaa)的最后一个,两对(aabb)的最后一个,而且符合最后匹配,所以直接从左开始模拟,两个bool,一个表示当前位前1,2位是否相等,另一个表示当前位的前2,3位是否相同。

    import java.util.*;
    
    
    public class Main implements Runnable{
    
        private final int mod = 1000000007, max = 200005;
    
        public static void main(String[] args) {
            new Thread(null, new Main(), "thread-1", 1024*1024*10).start();
        }
    
        @Override
        public void run() {
            try{
                solve();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    
        private void solve(){
            Scanner cin = new Scanner(System.in);
            int N = Integer.parseInt(cin.nextLine());
            StringBuilder sb = null;
            for(int i=0; i<N; ++i){
                sb = new StringBuilder();
                String source = cin.nextLine();
                boolean pIsDouble = false, ppIsDouble = false;
                int n = source.length();
                char pre = ' ';
    
                for(int j=0; j<n; j++){
                    if(pIsDouble && source.charAt(j) == pre){ //三连
                        continue;
                    }else if(!pIsDouble && ppIsDouble && source.charAt(j) == pre) {//两对
                        continue;
                    }else{
                        ppIsDouble = pIsDouble;
                        if(pre == source.charAt(j)){
                            pIsDouble = true;
                        }else {
                            pIsDouble = false;
                        }
                        pre = source.charAt(j);
                        sb.append(source.charAt(j));
                    }
                }
                System.out.println(sb);
            }
        }
    }
    
  3. 发奖品问题。n个人的分数围成一个环,任何一个人获得的奖品数量都比左右两个分数比自己低的人多,分数相等的话没有要求,求最小需要多少个奖品。设dp[i]表示给i发的最小奖品,首先扫一遍数组,将两侧分数均比中间高的位置,奖品数置1,然后再扫一遍对没有赋值的位置进行递归记忆化搜索。复杂度O(N)

    import java.util.*;
    
    
    public class Main implements Runnable{
    
        private final int mod = 1000000007, max = 100005;
    
        int[] arr = new int[max], dp = new int[max];
    
        public static void main(String[] args) {
            new Thread(null, new Main(), "thread-1", 1024*1024*10).start();
        }
    
        @Override
        public void run() {
            try{
                solve();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    
        private void solve() {
            Scanner cin = new Scanner(System.in);
            int T = cin.nextInt();
            for(int i=0; i<T; i++){
                int n = cin.nextInt();
                for(int j=0; j<n; j++){
                    arr[j] = cin.nextInt();
                    dp[j] = 0;//初始化dp数组
                }
                for(int j=0; j<n; j++){
                    if(arr[(j+1)%n] >= arr[j] && arr[(j-1+n)%n] >= arr[j]){ // 最优情况下,这里发的奖品一定是1
                        dp[j] = 1;
                    }
                }
    
                long ans = 0;
                for(int j=0; j<n; j++){
                    if(dp[j] == 0){
                        dfs(j, n);
                    }
                    ans += dp[j];
                }
                System.out.println(ans);
            }
        }
    
        void dfs(int k, int n) {
            int pre = (k-1+n)%n, nex = (k+1)%n;
            if(arr[pre] < arr[k] && dp[pre] == 0){
                dfs(pre, n);
            }
            if(arr[nex] < arr[k] && dp[nex] == 0){
                dfs(nex, n);
            }
    
            if(arr[pre] < arr[k]){
                dp[k] = Math.max(dp[k], dp[pre]+1);
            }
            if(arr[nex] < arr[k]){
                dp[k] = Math.max(dp[k], dp[nex]+1);
            }
        }
    }
    
  4. 剪绳子问题。一根绳子可以任意裁剪,但是不能拼接。一共n根,要搞出来m条相等的绳子,且长度最长,结果保留两位小数。二分答案求最大值。复杂度O(nlog2^31)。

    import java.util.*;
    
    
    public class Main implements Runnable{
    
        private final int mod = 1000000007, max = 100005;
    
        int[] arr = new int[max];
    
        public static void main(String[] args) {
            new Thread(null, new Main(), "thread-1", 1024*1024*10).start();
        }
    
        @Override
        public void run() {
            try{
                solve();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    
        private void solve(){
            Scanner cin = new Scanner(System.in);
            int n = cin.nextInt(),m = cin.nextInt();
            double lower = 0D, higher = Integer.MAX_VALUE;
            for(int i=0; i<n; i++){
                arr[i] = cin.nextInt();
            }
    
            while(higher - lower > 0.001){
                double mid = (lower+higher)/2;
                if(checkAns(n, m, mid)){
                    lower = mid;
                }else{
                    higher = mid;
                }
            }
            System.out.println(String.format("%.2f", lower));
        }
    
        boolean checkAns(int n, int m, double mid){
            int ans = 0;
            for(int i=0; i<n; i++){
                ans += (int)arr[i]/mid;
                if(ans >= m){
                    return true;
                }
            }
            return false;
        }
    }
    
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值