快手算法岗日常实习面试经验

快手算法岗日常实习面试经验

时间:2019.4.3 10:00 地点:北京市海淀区上地西路6号(快手总部)-E座

这次快手的面试一共两面,每一场面试都是先针对简历问问题然后手写一道算法题。由于我简历里科研的内容比较多,所以两位面试官都问了我关于我的一作在投论文的问题。由于是现场面试,所以代码是用笔写在草稿纸上然后面试官肉眼判题的。下面的面试流程就不叙述讨论论文的部分,只叙述手写算法题的部分。

一面

【二叉树形态变换】给定一个用中序遍历定义的二叉搜索树,用in-place的算法把二叉树变成有序链表,其中链表用左子树为null的二叉树等价表示。下面是例子,其中N表示null:
在这里插入图片描述

这道题类似LeetCode上的Flatten Binary Tree to Linked List,只不过LeetCode上原二叉搜索树是用先序遍历定义的。大致思路是一样的,都是在先序遍历或中序遍历的过程中加入节点指针的重定向操作,注意一下左子树或右子树为空的情形即可。更加详细的解题报告见我的博客LeetCode 114. Flatten Binary Tree to Linked List(二叉树)。LeetCode上那题的代码如下,可供参考:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    private TreeNode preorder(TreeNode root)
    {
        if (root == null)
        {
            return null;
        }
        TreeNode tmp = root.right, left_tail = preorder(root.left);
        if (root.left != null)
        {
            root.right = root.left;
        }
        root.left = null;
        if (left_tail != null)
        {
            left_tail.left = null;
            left_tail.right = tmp;
        }
        TreeNode right_tail = preorder(tmp);
        return right_tail == null ? (left_tail == null ? root: left_tail): right_tail;
    }
    
    public void flatten(TreeNode root) {
        preorder(root);
    }
}

二面

合并k个有序链表为一个有序链表。这是LeetCode上的原题:Merge k Sorted Lists. 我的做法是用一个优先队列维护k个链表的表头,每次从优先队列中取出队首元素作为合成链表的一个节点,并将所在链表的头指针后移并加入优先队列,如此循环直到优先队列为空。记合成链表的长度为n, 则建优先队列的复杂度为O(k), 从优先队列中取队首并将新元素插入优先队列的复杂度为O(logk), 这样的出队入队操作要重复n次,所以总复杂度为O(k+nlogk) = O(nlogk). 更加详细的解题报告见我的博客LeetCode 23. Merge k Sorted Lists(最小堆)。由于现场面试官允许使用Java自带的优先队列类,故我在面试现场没有手写一个最小堆来实现优先队列:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {  
    class Node {
        public int val;
        public int index;
        
        public Node(int val, int index)
        {
            this.val = val;
            this.index = index;
        }
        
        public Node(Node node)
        {
            this.val = node.val;
            this.index = node.index;
        }
    }
    
    public ListNode mergeKLists(ListNode[] lists) {
        int k = lists.length, i = 0, value = 0;
        if (k == 0)
        {
            return null;
        }
        PriorityQueue<Node> queue = new PriorityQueue<Node>(1, new NodeComparator implements Comparator<Node>() {
            @Override
            public int compare(Node n1, Node n2)
            {
                return n1.val - n2.val;
            }
        } );
        ListNode head = null, ret = null;
        for (i=0; i<k; i++)
        {
            if (lists[i] != null)
            {
                queue.add(new Node(lists[i].val, i));
                lists[i] = lists[i].next;
            }
        }
        if (queue.size() == 0)
        {
            return null;
        }
        while (!queue.isEmpty())
        {
            Node cur = queue.poll();
            if (head == null)
            {
                head = new ListNode(cur.val);
                ret = head;
            }
            else
            {
                head.next = new ListNode(cur.val);
                head = head.next;
            }
            if (lists[cur.index] != null)
            {
                queue.add(new Node(lists[cur.index].val, cur.index));
                lists[cur.index] = lists[cur.index].next;
            }
        }
        return ret;
    }
}

猜你喜欢

转载自blog.csdn.net/da_kao_la/article/details/89007032