小米面试
linux命令处理文本:
awk 将文本文件的内容按行读取,并可以指定分割符号,然后打印出具体某列的值。主要是用来处理列的。例如,某个data文件有多行,每行的字段以分号隔开,现要求打印出第3列的信息:cat data | awk -F ';' '{print $3}' 或者 awk -F ';' '{print $2}' data (-F指定分隔符)
sed命令也是处理每一行,它主要是对每一行的内容进行替换,但是它并没有修改源文件的内容,只是把修改后的内容输出而已。例如:将文本data中每一行中出现book的单词换成books:
sed 's/book/books/g' data (如果没有g,只能匹配并替换第一次出现的单词,如果有g,则全部替换)。sed -i 's/book/books/g' data 如果加了-i参数,则直接在文本中替换内容。
sort可以对每一行进行排序(按照首字母升序排序),uniq可以去除重复的行,但是必须是相邻的,所以通常需要结合sort命令和uniq命令一起使用。uniq -c 可以输出每行出现的次数(-c 代表count),sort -r 可以逆序排序(-r 代表reverse),head命令默认输出前10行,如果指定输出3行,则head -3。例如,某个data文件有多行,每行有一个单词,输出出现次数top 10 的单词:cat data | sort | uniq -c | sort -r | head
vi编辑一个文本,如果要在文本中显示每一行的行号,则
:set nu
算法题目:
1.
void find(int[] nums) { int sum=0, idx=-1; for(int i=0;i<nums.length;i++){ if(nums[i]==-1){ idx=i; }else{ sum+=nums[i]; } } System.out.println(5050-sum); System.out.println(idx); }
public class Main { public static void main(String[] args) { String a="10465"; String b="687"; System.out.println(minus(a,b)); } //将String(逆序)转换成数组,为数组每一位相减做准备 static int[] stringToArray(String str){ int length=str.length(); int[] arr=new int[length]; for(int i=0;i<str.length();i++){ //char类型的数字,通过这种方式变成int类型的数字 arr[i]=str.charAt(str.length()-1-i)-'0'; } return arr; } //将数组(逆序)转换成String作为结果输出 static String arrayToString(int[] a){ StringBuffer sb=new StringBuffer(); int i=a.length-1; //如果数组最末尾有0,则需要删除掉 while(i>=0 && a[i]==0 ){ i--; } for(;i>=0;i--){ sb.append(a[i]); } return sb.toString(); } private static String minus(String a, String b) { int[] x ; int[] y ; x=stringToArray(a); y=stringToArray(b); int jw=0; for(int i=0;i<y.length;i++){ //此处一定要加上进位 x[i]=x[i]+jw-y[i]; if(x[i]<0){ jw=-1; x[i]+=10; }else{ jw=0; } } int j=y.length; //如果第y位结束,则需要判断第y位之后的数字该怎么处理 while(jw == -1){ x[j]+=jw; if(x[j]<0){ x[j]+=10; j++; }else{ jw=0; } } return arrayToString(x); } }
3.
class Node{ public int value; public Node next; } //传入参数为一个指针,该头指针即代表整个链表 public boolean hascycle(Node head) { Node fast,slow; slow=fast=head; while(fast!=null && fast.next!= null){ fast=fast.next.next; slow=slow.next; if(fast==slow){ return true; } } return false; }
4.有一个非负整数数组,拼接起来组成小数点之后的部分,目标是拼接成一个最小的小数,String格式输出。
例如:[74,8,23,5]输出“0.235748”
[74,7,79,5]输出“0.574779”
思路:如何获得数字的每一位呢?先将数字转化成String类型的,然后通过charAt()获得每一位.
此题也需要技巧,不能暴力破解:即通过重写compare方法,重新定义数字的排序规则。
private static String calculateMin(int[] arr) { List<String> list=new ArrayList<String>(); StringBuffer sb=new StringBuffer(); sb.append("0."); for(int i=0;i<arr.length;i++){
//将int转换成String list.add(String.valueOf(arr[i])); } Collections.sort(list, new Comparator<String>() { public int compare(String o1, String o2) {
//得到两个数中较大的那个值 int len=Math.max(o1.length(), o2.length()); for(int i=0;i<len;i++){
//此步最重要,如果位数相同,则一位一位比较,如果不同(例如o1比o2长),那么之后比较o1的下一位与o2的第0位。 char ca=o1.charAt(i>(o1.length()-1)?0:i); char cb=o2.charAt(i>(o2.length()-1)?0:i); if(ca!=cb){ return ca>cb?1:-1; } } return 0; } }); for(String s:list){ sb.append(s); } return sb.toString(); } }
5.歌德巴赫猜想:任何一个大于4的偶数,都可以拆成两个质数的和。现在希望你在十万的范围内验证歌德巴赫猜想。如果猜想成立,输出OK,否则输出具体的反例。
思路:小学生的做法是,首先判断一个数a是否为质数(2,3,5,7,11,13,15,17...),让i从2增加到a/2(因为除数如果比被除数的一半还要大的,一定不能被整除),如果a%i==0(能整除)则说明a不是质数。如果a为质数,然后再判断偶数M-a是否也为质数。此种方法时间复杂度很高,因为除法在计算机中速度是最慢的,而且所有数字在判断为质数之后,还会一遍又一遍的进行判断。
大学生的做法是,用一个boolean数组保存每一位的值,如果第i位是质数则为T,否则为F,然后再将所有质数保存到素数表list中。
专家的做法是,费马小定理。
import java.util.ArrayList; import java.util.List; public class Main { static final int N = 100000;
//boolean数组 static boolean[] prime = new boolean[N + 1];
//素数表 static List<Integer> plist = new ArrayList<Integer>();
//首先获得100000以内的所有质数 static void getPrime() { int i, j; prime[0] = false; prime[1] = false; prime[2] = true; plist.add(2);
//先把所有偶数置为F for (i = 4; i <= N; i += 2) prime[i] = false;
//把所有奇数质为T for (i = 3; i <= N; i += 2) prime[i] = true; i = 3; while (i <= N) {
//从3开始,遇到奇数则加入到plist,遇到偶数则跳过 while (i <= N && !prime[i]) i++; if (i <= N) plist.add(i);
//如果i是质数,就把i的所有倍数全部置为F for (j = i + i; j <= N; j += i) { prime[j] = false; } i++; } } public static void main(String[] args) { getPrime(); for (int i = 6; i <= N; i += 2) { boolean found = false; for (int j = 0; j < plist.size(); j++) { int p = plist.get(j); if (i - p < 0) break;
//判断一个数是否为质数,直接通过boolean判断 if (prime[i - plist.get(j)]) { found = true; break; } } if (!found) { System.out.println(i); return; } } System.out.println("OK"); } }
1)如果两个链表都没有环,则说明是两条线性链,如果相交,只可能是Y型,不可能为X型。
首先遍历两个链表,记下两个链表的长度,长链表从起点先前进dif步,然后两个链表再一起前进,每次一步,相遇的第一个点即为相交的第一个点。
2)如果两个链表都有环,则不可能是环与环相交,只可能是两条线接一个圆。
3)如果一个链表有环,另外一个没有环,则必定不相交。
如何找到环的入口点?
head指针每次走一步,encounter指针也每次走一步,他们会在Entry(入口点)相遇。
证明:设慢指针slow每次走一步,快指针fast每次走两步,快慢指针的相遇点为encounter,环的入口点为Entry,head到Entry的距离为x,Entry到encounter的距离为y,r为环的长度。
当快慢指针相遇时,慢指针走的距离为s,快指针走的距离为2s,有
x+y=s
s+nr=2s
所以x+y=nr,刚好构成一个圆(假设n=1的话)。所以head指针走x,encounter指针也走x,刚好在Entry相遇。
Node findCycleEntry(Node head,Node encounter){ while(head!=encounter){ head=head.next; encounter=encounter.next; } return head; }
import java.util.Scanner; public class Main { static long getValue() { Scanner scan = new Scanner(System.in); String str = scan.nextLine(); long num = 0; //将字符串转换成long类型的整数,因为输入可能有回退键D for (int i = 0; i < str.length(); i++) { char ch = str.charAt(i); if (ch >= '0' && ch <= '9') { num = num * 10 + ch - '0'; } else { num = num / 10; } } return num; } 通过StringBuilder组合字符串 private static String translateToChinese(String s) { String[] unitArray = { "", "十", "百", "千", "万", "十", "百", "千", "亿", "十", "百", "千" }; String[] numArray = { "零", "一", "二", "三", "四", "五", "六", "七", "八", "九" }; StringBuilder sb = new StringBuilder(); for (int i = s.length() - 1; i >= 0; i--) { int num = s.charAt(i) - '0'; if (num != 0) { if (unitArray[s.length() - i - 1].equals("亿") && sb.charAt(0) == '万') { sb.setCharAt(0, '亿'); } else { //先放单位 sb.insert(0, unitArray[s.length() - i - 1]); } //再放数字 sb.insert(0, numArray[num]); } else { //处理数字中夹杂着零的情况 if (sb.length() != 0 && sb.charAt(0) != '零' && sb.charAt(0) != '万' && sb.charAt(0) != '亿') { sb.insert(0, numArray[num]); } if (unitArray[s.length() - i - 1].equals("万") || unitArray[s.length() - i - 1].equals("亿")) { if (sb.charAt(0) == '万') { sb.setCharAt(0, '亿'); } else { sb.insert(0, unitArray[s.length() - i - 1]); } } } } //如果是12,要求打印出十二,而不是一十二 if (sb.length() == 3 && sb.charAt(0) == '一') { sb.deleteCharAt(0); } return sb.toString(); } public static void main(String[] args) { while (true) { long value = getValue(); String s = String.valueOf(value); //边界值判断 if (s.length() > 12) { System.out .println("exceed the limit of length,please input a new number"); continue; } String chinese = translateToChinese(s); System.out.println(value); System.out.println(chinese); } } }