字节跳动(今日头条)推荐算法实习生面试

版权声明:本文为博主原创文章,欢迎大家转载,但是要注明我的文章地址。我的微信公众号【Microstrong】,分享机器学习、深度学习最新研究方向!一起来学习,一起来进步,一起来交流吧! https://blog.csdn.net/program_developer/article/details/80340829


2018-05-16 17:00 一面:

(1)自我介绍。

(2)介绍自己是如何去除水印和增加水印安全性的工作,对于自己做过的项目问的很具体。

(3)让详细介绍一下逻辑回归,包括逻辑回归的分类公式,损失函数、逻辑回归分类的过程。

(4)问了一下逻辑回归中损失函数的作用?

损失函数是评价模型的一个标准,它是衡量模型的预测值和真实值之间的误差的一种评价标准。

(5)逻辑回归中除了损失函数能衡量模型的好坏,还有没有其他的方法?

哎。。。自己悟性太低啦!问到这的时候,完全不知道面试官要问啥。现在想想应该是要问精度、错误率、准确率、召回率、ROC曲线和AUC面积等衡量模型的一些标准指标。

然后,这个问题面试官就说先过去吧!接着下一道。

(6)接下来,重点来了!字节跳动中传说的手撕代码来了!

面试官问:对数据结构和算法有没有了解啊!然后直接就给了一道算法题,先说思路,然后就是现场写代码。


题目:长度为n的数组中,总是存在一个断点(下标记为i),数组中断点前面的数字是有序的,断点后的数字也是有序的,且断点后边的数字总是小于前面的数字。如果直接把断点后边的数字移动到数组的前边,那么这个数组将是有序的,具体描述如下所示。求这个数组中的第n/2大的数。

原数组:
6,8,10,13,1,2,4
找到断点移动之后的数组:
1,2,4,6,8,10
#############################
原数组:
5,1,2,3,4,
找到断点移动之后的数组:
1,2,3,4,5
##############################
原数组:
2,3,4,5,1
找到断点移动之后的数组:
1,2,3,4,5

我的思路:先找到断点的下标i,然后根据下标直接取出第n/2(向上取整)大的元素。


1.如果你的第n/2大的数在断点后边,那么可以直接通过下标计算得出第n/2大的数的下标。下标计算公式如下:


2.如果你的第n/2大的数在断点的前面,那么你可以把断点后边小于第n/2大的数给算上,然后在往前面查找到第n/2大的数。下标计算公式如下:


public class Main {
	
	public static void main(String[] args){
//	    int[] array = {6, 8, 10, 13 , 1, 2, 4};
//		int[] array = {5, 1, 2, 3, 4};
		int[] array = {2, 3, 4, 5, 1};
	    int n = array.length;
	    int location = (int) Math.ceil(n/2.0);
	    int index = searchIndex(array);
	    int temp = 0;
	    if(location <= n - index){
	        temp = array[index+location - 1];
	    }else{
	        temp = array[location-(n-index+1)];
	    }
	    System.out.print(temp);
	}
	
	public static int searchIndex(int[] array){
	    for(int i=0; i<array.length; i++){
	        if(array[i] > array[i+1]){
	            return i + 1;
	        }
	    }
	    return 0;
	}
	    
}	

时间复杂度是O(n),空间复杂度是0。

这个算法时间复杂度是O(n),主要是在于查找断点的下标i时花费了时间。面试官让我来改进查找下标i的算法。我当时直接想出的是折半查找,面试官肯定了是折半查找算法。但是在思考用折半查找的时候,我自己遇到了两个细节问题,没有回答出来,所以这道题用折半查找没有回答出来。

遇到了两个细节问题是:

(1)我们要找数组中最小数的下标,那么我们前提是不知道最小数是多少,如何进行比较查找最小数。

(2)在折半查找的过程中,如何确定最小数是在左半边还是在右半边,换句话说,你是搜索左边的数组还是搜索右边的数组呢!

给出代码:

public class Main {
	
	public static void main(String[] args){
	    int[] array = {6, 8, 10, 13 , 1, 2, 4};
//		int[] array = {5, 1, 2, 3, 4};
//		int[] array = {2, 3, 4, 5, 1};
	    int n = array.length;
	    int location = (int) Math.ceil(n/2.0);
	    int index = Select_k(array, 0, n-1, location);
	    System.out.print(index);
	}
	
	 public static int quickSortOneTime(int[] array, int low, int high){ //一趟快速排序   
		 int  key = array[low];  
         while(low < high){  
        	while(key < array[high] && low < high)  high--;
            array[low] = array[high];  
            while(key > array[low] && low < high)   low++;  
            array[high] = array[low];
         }  
	    array[high] = key;  
	    return high;
	    }  
	 
	 public static int Select_k(int[] array, int low, int high, int k) {
		 int index;
		 if(low == high) return array[low];
		 int partition = quickSortOneTime(array, low, high);
		 index = high - partition + 1;  //找到的是第几个大值
		 if(index == k) {
			 return array[partition];
		 }else if(index < k) {//此时向左查找
			 return Select_k(array, low, partition-1, k-index);  //查找的是相对位置的值,k在左段中的下标为k-index
		 }else {
			 return Select_k(array, partition+1, high, k);
		 }
	 }
	    
}	

时间复杂度数O(logN)

详细介绍看我的这篇文章:

算法-在有序数组、无序数组中进行折半查找和二分法找无序数组中的第k小(大)的数

地址:https://blog.csdn.net/program_developer/article/details/80348077

展开阅读全文

没有更多推荐了,返回首页