字节跳动Android实习生视频面试(二面)

过程

一面过了一天就是二面,本来还想着二面会进一步考一些Android知识,就把Android绘制流程什么的都看了一遍,没想到二面聊会天之后纯考的算法orz,实在不擅长算法,虽然现在还没通知,但应该是凉了。

面试题目

首先是聊了聊简历上写的项目,差不多十几分钟吧,然后是算法题,全是手撕代码。如果我写得快的话,应该会问三道,但是我写太慢了,两道以后直接结束了。

  1. 链表反转
public static void main (String[] args) {
    Node head = new Node("a");  //一个具有三个节点的链表
    Node n1 = new Node("b");
    Node n2 = new Node("c");

    head.setNext(n1);  //设置节点指向情况
    n1.setNext(n2);
    n2.setNext(null);

    Node current = reverse(head);  //反转后的头结点
    while (current != null) {
        System.out.println(current.getContent());
        current = current.getNext();
    }
}

private static Node reverse(Node head) {
    if (head == null || head.getNext() == null)
        return head;
    Node pre = head;
    Node curr = head.getNext();
    Node next;
    pre.setNext(null);  //断开第二个节点指向头结点的链
    while (curr.getNext() != null) {
        next = curr.getNext();  //先得到next节点,不然断链以后无法获取
        curr.setNext(pre);
        pre = curr;
        curr = next;
    }
    curr.setNext(pre);  //还需最后单独断开尾结点指向倒数第二节点的链
    return curr;
}

Node类:

public class Node {
    private String content;
    private Node next;

    public Node(String content) {
        this.content = content;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public Node getNext() {
        return next;
    }

    public void setNext(Node next) {
        this.next = next;
    }
}

  1. 获取有序且具有重复元素的数组中某重复元素最左边元素的下标,要求时间复杂度为O(logn)
    For example : 有一个数组{1,2,3,3,3,3,4,4,5,6,6,7},输入3就输出2,输入4就输出6。
    显而易见,要让时间复杂度为O(logn),就会想到二分查找(然而我面试时没想到),废话不说上代码:
public static void main(String[] args) {
    int[] array = {1,2,3,3,3,3,4,4,5,6,6,7};
    int left = 0;
    int right = array.length - 1;
    int target = 3;  //要找的目标元素

    while (left < right) {
        int middle = (left + right) / 2;
        if (array[middle] < target) {  //目标在右半部分时,将左边界向右挪
            left = middle + 1;
        } else {  //目标在左半部分或横跨中间的数时,将右边界向左挪,这样就会得到重复元素最左边的值;
            right = middle;
        }
    }

    if (array[right] == target) {
        System.out.print("index is " + right);  //输出index is 2
    } else {
        System.out.print("not found");
    }
}

这样这道题就完了,但是我又想了想如果要获取最右边的元素该怎么办呢?首先想到把while循环改成如下形式:

while (left < right) {
    int middle = (left + right) / 2;
    if (array[middle] <= target) {  //这加了个等于号
        left = middle;  //这删掉+1
    } else {
        right = middle - 1;  //这加个-1
    }
}

本来以为在目标横跨中间的数的情况下,只需要把原来右边界左移改成左边界右移就可以,但是发现输入某些数值时循环不会停止。究其原因,int middle = (left + right) / 2为向下取整,假设当left = 4, right = 5时进入循环,middle = 4,进入第一个if中,又赋值left = 4,所以循环不会停止,所以应改成如下形式:

while (left < right) {
    int middle;
    
    if ((left + right) % 2 == 1){
        middle = (left + right) / 2 + 1;
    } else {
        middle = (left + right) / 2;
    }
    
    if (array[middle] <= target) {
        left = middle;
    } else {
        right = middle - 1;
    }
}

bingo

感想&结果

现在还没有收到消息,不出意外应该是凉了,不过这两次面试倒是学了不少东西,多面试也是增加经验。
大神看了就当乐呵乐呵,跟我一样的小菜鸡看了就当共同学习共同进步,没人看我就当自己学习之路上的记录了。

你可能感兴趣的:(面试记录)