小米面试

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.有一个一维数组int a[100],里面存储的是1到100的这100个数,不过是乱序存储;这时把其中某一位置的数值改成-1;请用最优的空间复杂性和时间复杂性求出该位置和值, 请写出代码, 语言不限。

思路:遍历数组得到-1的位置并记录,同时把非-1的值相加得到sum

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

 

 

2.有两个String类型的变量a, b, a的长度大于b, 两个变量都是由数字组成且长度均大于100, 求字符串变量代表的数字的差, 禁止使用java的BigInt等类似的类型.

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.如何判断一个单链表是否有环?
思路:设置两个快慢指针fast、slow,fast每次走两步,slow每次走一步,如果两个指针在将来某个时刻会相遇,则说明有环。
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"); } }

 

 

 

6.判断两个单向链表是否相交.

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;

}

 

 

7.面板:

1  2  3

4  5  6

7  8  9

0  D

显示屏:

123

一百二十三

要求:当面板中按顺序点击1,2,3时,显示屏对应显示两行,123和一百二十三,D是回退键,如果此时点击回退键,则显示12和十二。

写程序实现该功能,面板点击可以认为是标准输入,显示屏输出可以认为是标准输出。

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

    }

}

 

 

 

posted @ 2017-09-02 13:27  bili111  阅读(802)  评论(0编辑  收藏  举报