牛客网笔试题

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_20581563/article/details/51615496

昨天算法今天后端,又水了两把笔试…在这里把待解决的编程题整理一下,端午回来了填坑。

三角形个数

如图所示,N层对应的三角形个数为?(除了使用递推公式,感觉应该用递归的方法,没时间写了…)
三角形
ans
这里写图片描述
这里写图片描述

import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while (in.hasNextInt()) {//注意while处理多个case
            int N = in.nextInt();
            int result = countTriangles(N);
            System.out.println(result);
        }
    }

    private static int countTriangles(int N){
        if(N == 0 || N == 1) return N;

        int before = 1;
        int cur =  0;
        while(N>1){
            int one = 2*N-1;  //包含最后一层的边长为1的三角形个数
            int upright = N*(N-1)/2; //包含最后一层的其他边长的正立三角形个数
            int upsideDown = 0;
            if((N&1)==1) upsideDown = (N-1)*(N-3)/4; //N为奇数时,包含最后一层的其他边长的倒立三角形个数
            else upsideDown = (N-2)*(N-2)/4;  //N为偶数时,包含最后一层的其他边长的倒立三角形个数
            cur = one + upright + upsideDown + before;
            before = cur;
            N--;
        }

        return cur;
    }

}

钞票组合

输入:N (钞票的种类个数,1~10)
输入:M(要组合得到的重量,1~100)
输入:N个钞票对应的 value, minWeight, maxWeight
所有的都是int值。
输出:C(可能组合得到的钞票金额)
举例
输入:
2
50
1 15 20
3 30 30
输出:
2(一种是1+1+1=3,一种是1+3=4)
ans
回溯啊回溯…

import java.util.*;
import java.util.Map.Entry;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while (in.hasNextInt()) {
            int N = in.nextInt(); //输入钞票种类个数
            int M = in.nextInt(); //输入要组合得到的重量
            Map<Integer, List<Integer>> map = new HashMap<Integer, List<Integer>>();
            for(int i = 0; i < N; i++) {
                int value = in.nextInt();
                int minWeight = in.nextInt();
                int maxWeight = in.nextInt();
                List<Integer> list  = new ArrayList<Integer>();
                list.add(minWeight);
                list.add(maxWeight);
                map.put(value, list);
            }

            Set<Integer> moneySum = new HashSet<Integer>();
            backtracking(map, moneySum, 0, 0,M);
            System.out.println(moneySum);
            System.out.println(moneySum.size());
        }
    }

    private static void backtracking(Map<Integer, List<Integer>> map, Set<Integer> moneySum, int curMoneySum,int curWeightSum, int target){
        if(curWeightSum>target) return;
        if(curWeightSum==target){
            moneySum.add(curMoneySum);
            return;
        }

        Iterator<Map.Entry<Integer, List<Integer>>> iterator = map.entrySet().iterator();
        while(iterator.hasNext()){
            Map.Entry<Integer, List<Integer>> entry =  iterator.next();
            int newMoneySum = curMoneySum + entry.getKey();
            int newWeightSum1 = curWeightSum + entry.getValue().get(0);
            int newWeightSum2 = curWeightSum + entry.getValue().get(1);
            backtracking(map, moneySum, newMoneySum, newWeightSum1, target);
            backtracking(map, moneySum, newMoneySum, newWeightSum2, target);
        }
    }

}

要点一:选取合适的数据结构;
要点二:回溯。

生成回文

给定操作:用相邻两个数相加的结果替换这两个数。
问题描述:给你一个数列,如[3,1,1,1],问至少执行特定操作多少次,使其变为回文。
举例
输入:
4(数列中数字个数)
[3 1 1 1]
输出:
3
try
想了一种方法,判断两端大小,决定从小的那端加;如果两端相等(number[0]==number[n-1])就考虑1和n-2位上的情况,依次往里移动比较并选择是否相加。
编程实现不难,关键是有些数列本身就无法形成回文(可能题目有限定测试用例均为可以生成回文的数列?),由于testcase的欠缺,所以没有办法验证这种方法的正确性==试了几个简单的感觉是对的==

import java.util.*;
//由于牛客网通常都会对输入范围作出限制,所有省去了一些防御型代码==随意说一下==
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while (in.hasNextInt()) {
            int N = in.nextInt(); 
            int[] numbers = new int[N];
            for(int i=0;i<N;i++){
                numbers[i] = in.nextInt();
            }

            int cnt = countTimes(numbers);
            System.out.println(cnt);
        }
    }

    private static int countTimes(int[] numbers){
        int cnt = 0;
        int fromIndex = 0;
        int toIndex = numbers.length-1;
        while(!isPalindrome(numbers) && fromIndex<numbers.length/2){
            int index = findIndexOfMinNumber(numbers, fromIndex, toIndex);
            if(index<numbers.length/2){//位于左半部分,与后面那位相加,用二者的和替换这两个数
                numbers[index] = numbers[index]+numbers[index+1];
                numbers[index+1] = numbers[index];
                fromIndex = index;
                toIndex = (numbers.length-1)-fromIndex;
            }
            else{//位于右半部分,与前面那位相加,用二者的和替换这两个数
                numbers[index] = numbers[index]+numbers[index-1];
                numbers[index-1] = numbers[index];
                toIndex = index;
                fromIndex = (numbers.length-1)-toIndex;
            }
            cnt++;
        }
        return cnt;
    }

    private static boolean isPalindrome(int[] numbers){
        for(int i=0,j=numbers.length-1; i<j;i++,j--){
            if(numbers[i]!=numbers[j]) return false;
        }
        return true;
    }

    private static int findIndexOfMinNumber(int[] numbers, int fromIndex, int toIndex){
        while(fromIndex<toIndex){
            if(numbers[fromIndex] == numbers[toIndex] ) {
                fromIndex++;
                toIndex--;
            }
            else break;
        }
        return (numbers[fromIndex]<numbers[toIndex])?fromIndex:toIndex;
    }
}

最短完美子串

(超时了….目测应该用动态规划…)
字符串的完美度:只出现一次的字符个数
给定一个字符串,求出其中完美度最高且最短且最先出现的子串。

———————add:6/14/乐视——————————–

字符组合

输入:N(字符串的个数)
   str1 str2……..strN(N个字符串,每个字符串内的字符介于0~5之间)
输出: M(组合的个数,每个字符串取一个字符,不允许重复字符出现)
(有点乱。。原题更biantai,长长的故事)
举例
输入:2
   01 23
输出:4
输入:3
   01 10
输出:2
输入:3
   3 015 5
输出:2
ans
学习了牛客网讨论区的答案,就是把逗比的变量名改了改…递归啊递归…
乐视编程题代码讨论

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while (in.hasNextInt()) {
            int N = in.nextInt(); //输入派出的战士个数
            List<List<Integer>> defendNumbers = new ArrayList<List<Integer>>();
            for(int i = 0; i < N; i++) {
                String str = in.next();
                ArrayList<Integer> strList = new ArrayList<Integer>(); //每个战士能够对抗的敌人编号(0~6)
                for(char c: str.toCharArray()) {
                    strList.add(c - '0');
                }
                defendNumbers.add(strList);  //能够对抗的敌人编号列表((1)两个战士不能对抗同一个编号的敌人(2)每个战士对抗一个编号的敌人,如何组合?有多少种组合方法?)
            }
            int cnt = generateMethod(defendNumbers, N-1).size();
            System.out.println(cnt);
        }
    }

    public static List<Set<Integer>> generateMethod(List<List<Integer>> defendNumbers, int i) {
        if(i == 0) {
            List<Set<Integer>> res = new ArrayList<Set<Integer>>();
            for(int enermy: defendNumbers.get(0)) {
                Set<Integer> enermys = new HashSet<Integer>();
                enermys.add(enermy);
                res.add(enermys);
            }
            return res;
        } else {
            List<Set<Integer>> previousEnermySet = generateMethod(defendNumbers, i-1);
            List<Set<Integer>> res = new ArrayList<Set<Integer>>();
            for(Set<Integer> previousEnermys: previousEnermySet) {
                for(int enermy: defendNumbers.get(i)) {
                    if(!previousEnermys.contains(enermy)) {
                        Set<Integer> newEnermys = new HashSet<Integer>();
                        newEnermys.addAll(previousEnermys); 
                        newEnermys.add(enermy);
                        res.add(newEnermys);
                    }
                }
            }
            return res;
        }
    }
}
展开阅读全文

没有更多推荐了,返回首页