笔试题们

1、假设每一天适龄的母牛每年年初都会生一头小母牛,现在有一头刚出生的小母牛,问第N年时一共有多少头母牛?

Tips:
1 1
4 2
5 3

解析:假设f(n)代表的是今年母牛的数目,那么今年母牛的数目f(n-1)应该是去年的母牛的数目加上三年前母牛的数目f(n-3),即:

f(n) = f(n-1)+f(n-3)
难度指数:1颗星

代码如下:

public class Solution{
    public static int getTotalCows(int year){
        if(year < 4){
            return 1;
        }else{
            return getTotalCows(year-1) + getTotalCows(year-3);
        }
        }
}
以上是递归版本的解法,考虑到类似斐波那契的性能,可以将递归版本转成迭代版本,代码如下:
public class Solution{
    public static int getCowsInYearN(int year){
        if(year < 4) return 1;
        int[] cows = new int[year];
        for(int i=0; i < 3; i++){
            cows[i] = 1;
        }

        for(int i=3; i < year; i++){
            cows[i] = cows[i-1] + cows[i-3];
        }

        return cows[year-1];
    }
}

2、现在给出一份apache日志"access.log",请找出访问量为前十的IP地址。

日志内容如下:
62.30.142.174 - - [08/Jul/2010:05:24:10 +0800] "GET /index.html HTTP/1.0" 200 27
62.30.142.174 - - [08/Jul/2010:05:25:10 +0800] "GET /login.html HTTP/1.0" 200 27
72.30.142.174 - - [08/Jul/2010:05:27:10 +0800] "POST /redirct HTTP/1.0" 200 27
72.30.142.174 - - [08/Jul/2010:05:30:10 +0800] "GET /robots.txt HTTP/1.0" 200 27

解析:假设先不考虑日子文件的头部文件,整个log文件每一行都像这样。那么这个问题可以这样解,先从每一行中提取IP,将IP存入字典或哈希表中,然后提取前十个IP。

难度指数: 3颗星

python版的代码如下:

#-*- coding: utf-8 -*-
import os
import sys
import collections

def get_top_ten_ips(ip_list):
    ip_dict = collections.defaultdict(int)
    for ip in ip_list:
        ip_dict[ip] += 1

    ip_dict_items = sorted(ip_dict.items(), key=lambda d:d[1], reverse=True)
    sorted_ip_list = []
    for key, value in ip_dict_items:
        sorted_ip_list.append(key)
    return sorted_ip_list[0:10]

def main():
    ip_list = []
    with open("access.log") as log_file:
        for line in log_file:
            line = line.strip()
            if line:
                line_list = line.split()
                ip_list.append(line_list[0])
    print get_top_ten_ips(ip_list)

if __name__ == "__main__":
    main()

P.S.程序假设的是每一行的开头都是IP地址,假如不是的话可能还需要一个函数来判断是不是IP地址。
Java版的代码如下:

import java.util.*;
import java.io.*;

public class Solution{
static Map ipMap = new HashMap();
    static List ipList = new ArrayList();

    public static void getIpList(String fileName){
        try{
            BufferedReader reader = new BufferedReader(new FileReader(fileName));
            String line;
            while((line = reader.readLine()) != null){
                line = line.trim();
                String ip = getIpFromLine(line);
                if(ip != null){
                    ipList.add(ip);
                }
            }
        }catch(IOException ex){

        }
    }

    private static String getIpFromLine(String line){
        String[] strs = line.split(" ");
        if(strs.length > 1){
            return strs[0];
        }else{
            return null;
        }
    }

    public static List getTopTenIp(){

        for(String ipStr: ipList){
            if(ipMap.containsKey(ipStr)){
                ipMap.put(ipStr, ipMap.get(ipStr)+1);
            }else{
                ipMap.put(ipStr, 1);
            }
        }

        List> entryList = new ArrayList>(ipMap.entrySet());

        //对Map内容进行排序。
        Collections.sort(entryList, new Comparator>(){
            public int compare(Map.Entry oA, Map.Entry oB){
                return (oB.getValue() - oA.getValue());
            }
        });

        List topTenIp = new ArrayList<>();
        int i=0;
        for(Map.Entry ipEntry: entryList){
            topTenIp.add(ipEntry.getKey());
            i++;
            if(i >= 10) break;
        }

        return topTenIp;
    }

    public static void main(String[] args){
        getIpList("access.log");
        List result = getTopTenIp();
        for(String ip: result){
            System.out.println(ip);
        }
    }

}

对比Python和Java版的解法,显然Java的解法比Python复杂很多,甚至觉得在没有借助document的情况下,基本很难正确的写出来。
不过这个问题其实就是给你一堆IP地址(有重复),叫你找出重复次数最多的10个IP。也许有可以不用借助Map的解法,只是暂时没有想出来。

3、寻找循环数组的最小值,要求效率要高。
解析:寻找循环数组的最小值,遍历一次需要O(n)的时间,假如利用二分法查找,则可以在O(logn)时间内找到,难度系数1颗星。
答:

public class Solution{
    public static int findMin(int[] A){
        int left = 0;
        int right = A.length -1;
        int mid = (left+right)/2;

        while(left < right){
            mid = (left+right)/2;

            if(A[mid] < A[left]){
                right = mid;
            }else if(A[mid] > A[left]){
                left = mid;
            }else{
                mid++;
                break;
            }
        }

        int min = (A[mid] < A[0]) ? A[mid]:A[0];
        return min;
    }
}

4、给出一个字符串,去除字符串中"a"、"bc"等字串,比如,"abcbac"结果为""。要求:只能遍历字符串一次,不能用额外空间。
解析:呃,这道题摆明了就只能用C/C++来解决,因为Java/Python等语言字符串是不可改变的,new一个字符串也算是额外空间。难度系数1颗星。
答:

#include<stdio.h>

int main(int argc, char* argv[]){
    char str[] = argv[1]

    int numOfB = 0;
    int i;
    int j;
    for(i=0; str[i] != '\0'; i++){

        if(str[i] == 'a'){
            j=i+1;
            while(str[j] != '\0'){
                str[j-1] = str[j];
                j++;
            }
            str[j-1] = '\0';
        }

        if(str[i] == 'b'){
            numOfB += 1;
        }

        if(str[i] == 'c' && numOfB > 0){
            j = i+1;
            while(str[j] !='\0'){
                str[j-2] = str[j];
                j++;
            }
            str[j-2] = '\0';
            numOfB -= 1;
        }else if(str[i] != 'b'){
            numOfB = 0;
        }
    }

    printf("%s\n", str);
}

5、实现定时功能,每一分钟打印出“我面试要成功”。
解析:简单实现定时功能可以用Thread.sleep,但是有一个疑问是是否可以休眠一分钟,验证是可以的。也可以利用TimerTask类来实现,或者J2SE5以上可以用ScheduledExecutorService来实现定时功能。

import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ScheduledExecutorService;

class SimpleTaskTimer implements Runnable{
    private final long intervalTime = 60*1000;

    @Override
    public void run(){
        while(true){
            System.out.println("我面试要成功");
            try{
                Thread.sleep(intervalTime);
            }catch(InterruptedException e){
                e.printStackTrace();
            }
        }
    }
}

class TimerUseTimerTask{
    private final long delay = 0;
    private final long intervalTime = 60*1000;

    public void start(){

        TimerTask task = new TimerTask(){
            @Override
            public void run(){
                System.out.println("我面试要成功");
            }
        };

        Timer timer = new Timer();
        timer.scheduleAtFixedRate(task, delay, intervalTime);
    }
}

class TimerUseExecutor{
    private final long delay = 0;
    private final long intervalTime = 60;
    public void start(){
        Runnable runnable = new Runnable(){
            @Override
            public void run(){
                System.out.println("我面试要成功");
            }
        };

        ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
        service.scheduleAtFixedRate(runnable, delay, intervalTime, TimeUnit.SECONDS);
    }
}

public class WongTimer{
    public static void main(String[] args){
        Thread simpleTaskTimer = new Thread(new SimpleTaskTimer());
        simpleTaskTimer.start();

        TimerUseTimerTask timerUseTimerTask = new TimerUseTimerTask();
        timerUseTimerTask.start();

        TimerUseExecutor timerUseExecutor = new TimerUseExecutor();
        timerUseExecutor.start();

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值