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(); } }