那是最好的年代,也是最糟的年代。那是光明的时节,也是黑暗的时节。那是希望的春季,也是悲伤的冬日。
2019 我开始了自己的求职之旅。2个月以来,面试了10多家公司。外面整体形势很差,比自己想象的还要差。一方面各大厂hc大大减少,要求也大大提升。总体感觉这次,自己很被动。所以,以后要做更好的计划。
- 简历每3个月要进行一次更新。
- 时刻保持自己对leetcode题型的熟知程度,总之,时刻准备着....优秀是一种习惯
- 面试过程,一定注意编程题的细节,一定不要着急给自己挖坑,挖与不挖是智商与情商的双重考验
- 面试的时候,首先拿小厂积累经验,弥补不足,循序渐进,厚积薄发。记住没有没有价值的面试。涨不了技术,就涨阅历。不断的面试练习,最后巅峰时刻,去面大厂。
- 面试中当和面试官意见不一致时,要保持沉默,不要据理力争。同时还要注意面试官是不是给自己挖坑,不能啥都附和。总之,面试在缘分。
- 一定要给自己设置一个找工作的战线区间,比如一个月,比如2个月,战线千万不要啦太长。无论如何,就是一个月,我必须在我拿到的offer里面挑一个去,有压力才会有动力。
- 最佳的找工作时间还是3,4月,9,10月。其他时间机会相对较少。
总体面试经验分享如下,
2019.2.22
瑞途科技
公司只要是对地铁隧道中的墙壁裂缝,遗留物等检测的。有自己的嵌入式设备。
技术leader主要聊了一些工作经验。
2019.2.22
当当网
对方的岗位主要偏大数据方向,我主要是做cv方向,抱着试一试的态度面试。
面试主要5个环节。
1,做试卷
题型主要是选择题,问答题,编程题。
问答题
- PCA,LDA区别
PCA为非监督降维,LDA为有监督降维
PCA希望投影后的数据方差尽可能的大(最大可分性),因为其假设方差越多,则所包含的信息越多;而LDA则希望投影后相同类别的组内方差小,而组间方差大。LDA能合理运用标签信息,使得投影后的维度具有判别性,不同类别的数据尽可能的分开。
- AUC
- 机器学习的其他使用过的方法,评价指标
编程题
(1)给定一个输入正整数N,输出N的阶乘的值。(N<512)
要考虑大整数乘法溢出的问题。
主要思想:
初始值为1.
然后把1放入数组存着,(按位存,比如999,即f[0]=9, f[1]=9, f[2]=9)
然后数组的每一位都乘以2,(注意还有进位)
然后数组的每一位都乘以3,…
然后数组的每一位都乘以n.
最后从后往前,输出每一位即是结果。注意,数组后面从非0开始计算。即最高位就是第一个非0位。
#define Max 512 //最多存储3000位
int main()
{
int n=3; //输入的数
int temp;
int f[Max] = { 1, 0 }; //用于存储结果的每一位数
int i, j;
for (i = 2; i <= n; i++)
{
int flag = 0;//进位标志
for (j = 0; j < Max; j++) //对于每一个数i,把f中的每一个数字(即下标j的数字)都剩以i,注意进位
{
temp = f[j] * i + flag;
f[j] = temp % 10;
flag = temp / 10;
}
}
for (j = Max - 1; j >= 0; j--)
if (f[j]) break;
for (i = j; i >= 0; i--)
std::cout << f[i];
std::cout << std::endl;
return 0;
}
(2)给定一个input.txt,里面存着用户购买的书的编号,可以理解为一行一个字符串,大概1000w行,输出购买量前100的书的编号。
由于数据量大,需要将1000w的数据分成N份(这里为了保证相同的数据被分到同一个桶,得使用hash函数),每份取前100个,再对N份的前100进行排序,输出最终的前100项。
import hashlib
def hash_func(string_data,num_split=10):
md5 = hashlib.md5()
md5.update(string_data.encode('utf-8'))
return sum(ord(x) for x in md5.hexdigest())%num_split
file=open("input.txt","r",encoding="utf-8")
lines=file.readlines()
file.close()
num_split=10
out_pre_num=100
lines_bucket=[]
for i in range(num_split):
lines_bucket.append({})
for line in lines:
line=line.rstrip("\n")
hash_num=hash_func(line,num_split)
if line in lines_bucket[hash_num].keys():
lines_bucket[hash_num][line]+=1
else:
lines_bucket[hash_num][line]=1
bucket_pre_100_lists=[]
for i in range(len(lines_bucket)):
lines_bucket_sorted_lists=sorted(lines_bucket[i].items(),key=lambda x:x[1],reverse=True)
bucket_pre_100_lists.extend(lines_bucket_sorted_lists[:out_pre_num])
sorted_pre_100_lists=sorted(bucket_pre_100_lists,key=lambda x:x[1],reverse=True)
print(sorted_pre_100_lists[:out_pre_num])
2.技术1面试
聊项目经验+2道编程题
- leetcode ,3Sum
思路,夹逼准则
S=[-1,0,1,2,-1,-4]
sum_3=0
output=[]
S=sorted(S,reverse=False)
for i in range(len(S)):
if i>0 and S[i]==S[i-1]:
continue
fore_index=i+1
back_index=len(S)-1
target=sum_3-S[i]
print(i)
while fore_index<back_index:
if S[fore_index]+S[back_index]==target:
output.append((S[i],S[fore_index],S[back_index]))
fore_index+=1
back_index-=1
elif S[fore_index]+S[back_index]<target:
fore_index+=1
else:
back_index-=1
print(output)
2.给定2个字符串,判断第一个字符串中是否按顺序的包含第二个字符串中的每个字符。
例如,字符串A=”zcfdkwuy”,字符串B=”zku”,则A字符串按顺序包含B字符串的每个元素,返回True,不包含返回False
A="zcfdkwuy"
B="zku"
index_A=0
index_B=0
while index_A<len(A) and index_B<len(B):
if A[index_A]==B[index_B]:
index_A+=1
index_B+=1
else:
index_A+=1
output=index_B>=len(B)
print(output)
3.技术2面试
聊项目经验+2道编程题
(1)给定一个排序后的数组A,输出该数组中任意2个数的和为给定数X的索引
和Two Sum这道题的区别就是,Two Sum输入的数组不要求是已经排序的。而这块是已经排序的,我也没闹懂出题人的意思,直接就想了二分查找(时间复杂度o(n*log(n))),其实后来一想,基于hash的思路要比这个高效(时间复杂度o(n))。
二分查找思路,
def binary_search(data_list,first,last,key):
while first<=last:
middle=int(first+(last-first)/2)
if data_list[middle]==key:
return middle
if key<data_list[middle]:
last=middle-1
if data_list[middle]<key:
first=middle+1
print(first,last,key)
return -1
A=[1,3,5,6,7,9]
X=8
output_list=[]
for num,i in enumerate(A):
out_index=binary_search(A,0,len(A)-1,X-i)
if out_index!=-1 and out_index>num:
output_list.append((num,out_index))
print(output_list)
Hash思路,
A=[1,3,5,6,7,9]
X=8
output_list=[]
for num,i in enumerate(A):
out_index=-1
if X-i in A:
out_index=A.index(X-i)
if out_index>num:
output_list.append((num,out_index))
print(output_list)
第二题忘了。
4,部门leader面试
5,hr面
上海欧拉:
new与malloc的区别:
(1)分配内存的位置,
new(自由存储区),malloc(堆)
(2)内存分配失败返回值
new(完整类型指针),malloc(void*指针)
(3)内存分配失败返回值
new(默认抛出异常),malloc(NULL)
(4)分配内存的大小
new(编译器根据类型计算得出),malloc(必须显式指定字节数)
(5)已分配内存的扩充
new(无法直观地处理),malloc(使用realloc简单完成)
(6)是否相互调用
new(可以调用malloc),malloc(不可以调用new)
(7)函数重载
new(容许),malloc(不容许)
(8)构造函数与析构函数
new(调用),malloc(不调用)
虚函数:
虚函数可以在子类方法中进行重载,也可以不重载而沿用父类的方法。
纯虚函数必须重载,因为声明类中没有函数的实现,virtual void func()=0;
包含纯虚函数的类为抽象类,不能声明对象,只能作为基类。
意锐新创:
技术面+leader面
直接聊经验,公司主要做移动二维码支付,小白盒
面试经验收获少,人生阅历有收获。
翔创科技:
京东人脸识别大赛第二名,主要做人工智能养猪。初创公司,直接聊技术。
卓视智通:
公司主要做安防,老板很年轻,初创公司,主要聊技术。
申哲伙伴:
面试题,
(1)1个箱子里有50个红球,50个蓝球。每次从里面取出2个。
如果是2个红色,全部放回,
如果是2个蓝色,全部取出蓝色,
如果是一个红色,一个蓝色,取出1个红色,放回一个蓝色,
求,最后剩下红色的概率。
单场懵逼,没啥思路。可以模拟10000次试验计算,但是肯定有更好的办法,只是没想到。结果应该是0.5。
取出,红,蓝 | 1/2(红蓝+蓝红两种情况) |
取出,红,红 | 1/4 |
取出,蓝,蓝 | 1/4 |
import random
#求最后剩下红球的概率
num_temp=0
num_all=num_all_copy=10000
while num_all>0:
num_all-=1
red_ball_num=50#0表示
blue_ball_num=50#1表示
while True:
num1=random.randint(0,1)
num2=random.randint(0,1)
if (num1==0 and num2==1) or (num1==1 and num2==0):
red_ball_num-=1
elif num1==0 and num2==0:
pass
elif num1==1 and num2==1:
blue_ball_num-=2
else:
pass
if blue_ball_num==0 and red_ball_num>0:
num_temp+=1
break
if blue_ball_num>0 and red_ball_num==0:
break
perception=num_temp/num_all_copy
print(perception)#0.5
(2)RPN网络可不可以做多分类任务。
(3)项目经验。
一起教育:
编程1,编辑距离,
int minDistance(const string &word1, const string &word2) {
const size_t n = word1.size();
const size_t m = word2.size();
// 长度为 n 的字符串,有 n+1 个隔板
int f[n + 1][m + 1];
for (size_t i = 0; i <= n; i++)
f[i][0] = i;
for (size_t j = 0; j <= m; j++)
f[0][j] = j;
for (size_t i = 1; i <= n; i++) {
for (size_t j = 1; j <= m; j++) {
if (word1[i - 1] == word2[j - 1])
f[i][j] = f[i - 1][j - 1];
else {
int mn = min(f[i - 1][j], f[i][j - 1]);
f[i][j] = 1 + min(f[i - 1][j - 1], mn);
}
}
}
return f[n][m];
}
编程2,kmeans
#!/usr/bin/python
# coding=utf-8
import numpy as np
import random
import math
import copy
import matplotlib.pyplot as plt
dataMat=[[1.658995,4.285136],
[-3.453687,3.424321],
[4.838138,-1.151539],
[-5.379713,-3.362104],
[0.972564,2.924086],
[-3.567919,1.531611],
[0.450614,-3.302219],
[-3.487105,-1.724432],
[2.668759,1.594842],
[-3.156485,3.191137],
[3.165506,-3.999838],
[-2.786837,-3.099354],
[4.208187,2.984927],
[0.704199,-0.479481],
[-0.392370,-3.963704],
[2.831667,1.574018],
[-0.790153,3.343144],
[2.943496,-3.357075]
]
# 计算欧几里得距离
def distEclud(centroids, datai):
dis=[]
for i in range(len(centroids)):
dis.append(math.sqrt((centroids[i][0] - datai[0])**2+(centroids[i][1] - datai[1])**2))
return dis
# 构建聚簇中心,取k个(此例中为4)随机质心
def randCent(dataSet, k):
min_x = min(dataSet[:][0])
max_x = max(dataSet[:][0])
min_y = min(dataSet[:][1])
max_y = max(dataSet[:][1])
centroids = []
for i in range(k):
centroids.append([random.uniform(min_x,max_x),random.uniform(min_y,max_y)])
return centroids
#centroids = set()
#while len(list(centroids))<k:
# centroids.add(random.randint(0,len(dataSet)))
#return list(centroids)
# k-means 聚类算法
def kMeans(dataSet, k):
m = len(dataSet)
# clusterAssment第一列存放该数据所属的中心点,第二列是该数据到中心点的距离
centroids = randCent(dataSet, k)
pre_centroids=copy.copy(centroids)
while True:
clusterAssment = [] # 用于存放该样本属于哪类及质心距离
for i in range(m): # 把每一个数据点划分到离它最近的中心点
distJI = distEclud(centroids, dataSet[i])
clusterAssment.append([distJI.index(min(distJI)),min(distJI)])
minDst=0
for j in range(k): # 重新计算中心点
sum_k_x=0
sum_k_y=0
num_k=0
for n in range(len(clusterAssment)):
if clusterAssment[n][0]==j:
sum_k_x+=dataSet[n][0]
sum_k_y+=dataSet[n][1]
num_k+=1
centroids[j]=[sum_k_x/(num_k+0.0001),sum_k_y/(num_k+0.0001)]
minDst+=math.sqrt((centroids[j][0]-pre_centroids[j][0])**2+(centroids[j][1]-pre_centroids[j][1])**2)
if minDst<0.5:
break
else:
pre_centroids=copy.copy(centroids)
return centroids, clusterAssment
# --------------------测试----------------------------------------------------
# 用测试数据及测试kmeans算法
myCentroids,clustAssing = kMeans(dataMat,4)
print (myCentroids)
print (clustAssing)
c_lists=['b','g','k','y']
marker_lists=['x','1','2','s']
fig = plt.figure()
axis = fig.add_subplot(111)
for i in range(len(dataMat)):
axis.scatter([dataMat[i][0]], [dataMat[i][1]], c = c_lists[clustAssing[i][0]],marker = marker_lists[clustAssing[i][0]])
axis.scatter([myCentroids[i][0] for i in range(len(myCentroids))], [myCentroids[i][1] for i in range(len(myCentroids))], c = 'r',marker = 'o')
plt.show()
微店:
3个技术面,1个hr
程序题,
- 一个贝叶斯的英文题,没细看,直接说了不会。
- 给定2个数组,判断另外一个数组是否是由第一个数组中的元素进行打乱得到的。
例如,数组,A=[1,3,5,4,7],B=[1,5,7,4,3],则数组B中元素和数组A中元素相等,返回True。
方法1,可以将2个数组分别进行排序,然后看排序后结果是否相等。o(nlogn)时间
方法2,遍历A数组,将其中的元素进行哈希存储,然后遍历B数组,判断哈希表中的数值。o(n)时间
智力题,
- 一个固定大小的桌子,有无数的固定大小的硬币。A,B两人一人每次放一枚,不容许重叠的放。直到不能再放为止,轮到谁不能再放,就算谁输,假设A先放,A怎么样保证自己一定赢。
放中心位置。因为桌子是关于中心对称的,只有中心位置只有1个。只要占了中心位置。这样不管B怎么放,A都可以放在B的放的位置的对称位置。
- 逻辑回归,假设有100个特征向量,将其中的一个特征复制100次,生成200个维度的特征向量,问这样训练和原来的100维的训练会有区别吗?
不会有区别,假设复制的那个向量的分数为p,这样最记得假设,复制后每个向量的分数为p/101,和原来的向量还是一样的。
58同城:
聊项目经验
小鹏汽车:
聊项目经验
问了一些构造函数的多态。
Lstm手写公式,
Svm推导
Face++:
(1)NMS
import numpy as np
def nms(dets, thresh):
#dets[x1,y1,x2,y2,p]
dets=sorted(dets,key=lambda x:x[4],reverse=True)
delete_lists=[]
for n,xy in enumerate(dets):
if dets [n][4]=0:
continue
for num,xxyy in enumerate(dets[n+1:]):
if dets [n+1+num][4]=0:
continue
xx1 = np.maximum(xy[0], xxyy[0])
yy1 = np.maximum(xy[1], xxyy[1])
xx2 = np.minimum(xy[2], xxyy[2])
yy2 = np.minimum(xy[3], xxyy[3])
w = np.maximum(0.0, xx2 - xx1 + 1)
h = np.maximum(0.0, yy2 - yy1 + 1)
inter = w * h
union= (xy[2]-xy[0])*(xy[3]-xy[1])+(xxyy[2]-xxyy[0])*(xxyy[3]-xxyy[1])
ovr = inter / (union - inter+0.00001)
if ovr >= thresh:
dets [n+1+num][4]=0
delete_lists.append(n+1+num)
dets=np.delete(dets,delete_lists,axis=0)
return dets
(2)单链表反转
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};
ListNode* ReverseList(ListNode* pHead) {
ListNode *root=pHead;
ListNode *pre=NULL;
ListNode *next=NULL;
if(pHead==NULL) return NULL;
while(root->next){
next=root->next;
root->next=pre;
pre=root;
root=next;
}
root->next=pre;
return root;
}
美图:
3个技术面,1个hr面,
(1)线性回归和逻辑回归区别。
线性回归用来预测,逻辑回归用来分类。
线性回归是拟合函数,逻辑回归是预测函数
线性回归的参数计算方法是最小二乘法,逻辑回归的参数计算方法是梯度下降
(2)偏差和方差区别
偏差: 描述模型输出结果的期望与样本真实结果的差距。
方差: 描述模型对于给定值的输出稳定性。
泛化性能=偏差+方差+noise
[高方差] (过拟合)解决思路:
采集更多的样本数据,减少特征数量,去除非主要的特征,增加正则化参数 λ
[高偏差] (欠拟合)解决思路:
引入更多的相关特征,采用多项式特征,减小正则化参数 λ
(3)类似百度的相似图片查找
KNN,KD Tree,矩阵运算加速等。
(4)分类和回归的区别。
分类是离散的,定性的,回归是连续的,定量的
编程题,
两个list转化为一个dict,
list1 = ['key1','key2','key3']
list2 = ['1','2','3']
dict(zip(list1,list2))
支付宝:
神经网络训练,很多时候彩色图训练和灰度图训练效果差不多,比如人脸识别中,那么颜色到底是不是一种特征?
当时被问到这个,自己也是左右纠结,传统算法中,颜色确实是一个特征,比如itti。人脸识别训练确实是灰度图和彩图没啥区别,有些ocr中甚至灰度图效果更好。
于是自己pytorch路了个简单的例子验证。
造图片程序:
import cv2
import numpy as np
import random
image_shape=56
shape_type=["triangle","rectange","circle"]
color_shape=[(0,0,255),(0,255,0),(255,0,0)]
color_shape_name=["red","green","blue"]
image_class_num=20
dataset_folder="data/"
for cn,color_type in enumerate(color_shape):
for ic_num in range(image_class_num):
image=np.ones((image_shape,image_shape,3), np.uint8)*255
shape=shape_type[random.randint(0,2)]
if (shape=="triangle"):
pts = np.array([[random.randint(5,image_shape),random.randint(5,image_shape)],[random.randint(5,image_shape),random.randint(5,image_shape)],[random.randint(5,image_shape),random.randint(5,image_shape)]], np.int32)
pts = pts.reshape((-1,1,2))
image = cv2.polylines(image,[pts],True,color_type,1)
image=cv2.fillPoly(image, [pts], color_type);
elif (shape=="rectange"):
x1=random.randint(1,image_shape-10)
y1=random.randint(1,image_shape-10)
x2=x1+random.randint(5,image_shape-x1)
y2=y1+random.randint(5,image_shape-y1)
image=cv2.rectangle(image,(x1,y1),(x2,y2),color_type,-1)
elif (shape=="circle"):
center_x=random.randint(5,image_shape-5)
center_y=random.randint(5,image_shape-5)
radius=random.randint(5,min(min(center_x,center_y),min(image_shape-center_x,image_shape-center_y)))
image=cv2.circle(image,(center_x,center_y), radius, color_type, -1)
else:
pass
cv2.imwrite(dataset_folder+color_shape_name[cn]+"_"+shape+"_"+str(ic_num)+".jpg",image)
图片大小56*56,形状分为三角形,圆形,四边形,颜色分为红,绿,蓝。每一个颜色都包含这三种形状。也就是说颜色是唯一的分类特征。
训练和测试程序:
#dataset.py
import os
from PIL import Image
import cv2
import torch
from torch.utils import data
from torchvision import transforms
from torchvision.transforms import functional as F
import numbers
import numpy as np
import random
class ImageData(data.Dataset):
def __init__(self,train_root):
self.image_root = train_root
self.image_list = os.listdir(self.image_root)
self.image_num=len(self.image_list)
self.label_dict={"red":0,"green":1,"blue":2}
def __getitem__(self, item):
im_name = self.image_root+self.image_list[item % self.image_num]
image = load_image(im_name)
image = cv_random_flip(image)
label = self.label_dict[self.image_list[item % self.image_num].split("_")[0]]
#彩图注释该行
image= np.expand_dims(np.sum(image,axis=0)/3,axis=0)
sample = {'image': image, 'label': label}
return sample
def __len__(self):
return self.image_num
def get_loader(mode='train'):
if mode == 'train':
shuffle = True
dataset = ImageData("./data/train/")
data_loader = data.DataLoader(dataset=dataset, batch_size=100, shuffle=shuffle, num_workers=2)
else:
shuffle = False
dataset = ImageData("./data/test/")
data_loader = data.DataLoader(dataset=dataset, batch_size=100, shuffle=shuffle, num_workers=2)
return data_loader
def load_image(path):
if not os.path.exists(path):
print('File {} not exists'.format(path))
im = cv2.imread(path,1)
in_ = np.array(im, dtype=np.float32)
in_ -= np.array((104.00699, 116.66877, 122.67892))
in_ = in_.transpose((2,0,1))
return in_
def cv_random_flip(img):
flip_flag = random.randint(0, 1)
if flip_flag == 1:
img = img[:,:,::-1].copy()
return img
#train_test.py
import os
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torch.autograd import Variable
from dataset import get_loader
print(torch.__version__)
os.environ["CUDA_VISIBLE_DEVICES"] = '0'
EPOCHS=50 # 总共训练批次
DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu") # 让torch判断是否使用GPU,建议使用GPU环境,因为会快很多
class ConvNet(nn.Module):
def __init__(self):
super().__init__()
self.conv0=nn.Conv2d(1,20,5) # 10, 24x24#彩图修改输入为3
self.conv1=nn.Conv2d(20,20,5)
self.conv2=nn.Conv2d(20,40,3)
self.fc1 = nn.Linear(1960,100)
self.fc2 = nn.Linear(100,3)
def forward(self,x):
in_size = x.size(0)
out = self.conv0(x)
out = F.max_pool2d(out, 2, 2)
out = self.conv1(out)
out = F.relu(out)
out = self.conv1(out)
out = F.relu(out)
out = F.max_pool2d(out, 2, 2)
out = self.conv2(out)
out = F.relu(out)
out = out.view(in_size,-1)
out = self.fc1(out)
out = F.relu(out)
out = self.fc2(out)
out = F.log_softmax(out,dim=1)
return out
model = ConvNet().to(DEVICE)
optimizer = optim.Adam(model.parameters(),lr = 0.0001)
criterion = nn.CrossEntropyLoss()
def train(model, device, train_loader, optimizer, epoch):
model.train()
for batch_idx, data_target in enumerate(train_loader):
data, target = Variable(data_target['image']).to(device), Variable(data_target['label']).to(device)
optimizer.zero_grad()
output = model(data)
loss = F.nll_loss(output, target)
#loss = criterion(output, target)
loss.backward()
optimizer.step()
if(batch_idx+1)%10 == 0:
print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
epoch, batch_idx * len(data), len(train_loader.dataset),
100. * batch_idx / len(train_loader), loss.item()))
def test(model, device, test_loader):
model.eval()
test_loss = 0
correct = 0
with torch.no_grad():
for data_target in test_loader:
data, target = data_target['image'].to(device), data_target['label'].to(device)
output = model(data)
test_loss += F.nll_loss(output, target, reduction='sum').item() # 将一批的损失相加
pred = output.max(1, keepdim=True)[1] # 找到概率最大的下标
correct += pred.eq(target.view_as(pred)).sum().item()
test_loss /= len(test_loader.dataset)
print('\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format(
test_loss, correct, len(test_loader.dataset),
100. * correct / len(test_loader.dataset)))
for epoch in range(1, EPOCHS + 1):
train(model, DEVICE, get_loader(mode='train'), optimizer, epoch)
test(model, DEVICE, get_loader(mode='test'))
灰度图训练结果:
彩图训练结果:
最终结论,
灰度图的准确性略高于平均准确性33%,彩图准确性基本100%。。可见颜色也是一种神经网络可以学习的特征。所以可以根据实际应用场景,增加或者去掉颜色特征。
高德
1面电话聊项目经验
2面现场面,项目经验为主,一些基本框架
3面现场面,主要编程,
编程1,IOU,需要定义结构体
编程2,二叉树翻转,求深度
int maxDepth(TreeNode *root) {
if (root == nullptr) return 0;
return max(maxDepth(root->left), maxDepth(root->right)) + 1;
}
void exchange(TreeNode *root) {
if (root == nullptr) return;
TreeNode *temp=root->right;
root->right=root->left;
root->left=temp;
exchange(root->left);
exchange(root->right);
}
编程3,2sum,o(n)的怎么处理,o(n*log(n))怎么处理?
Hashmap,二分查找,左右夹逼。
京东:
1面,2面,聊项目经验,以及一些遇到的问题怎么处理
3面,leader聊一些工作情况
4面,hr
作业帮:
1面,2面聊项目经验。3面,hr小姐姐面。
笔试题,
检测恶意访问的服务IP。假设一个服务访问,可以得到IP,访问时间,假设连续的10秒内,同一个IP的访问超过10次,就算该IP为恶意访问的IP。假设没有大量的并发情况。
思路,定义一个queue,每次来了访问服务,就加入该queue。定义一个hashmap,里面存储所有的IP。如果超过10秒,就将该hash对应的访问次数值清零。否则就加1。如果超过10次就证明是恶意访问。
#include <iostream>
#include <queue>
#include <utility>
#include <string>
#include <unordered_map>
using namespace std;
struct MALICE{
float time;
int count;
MALICE(float t, int c) :time(t), count(c){};
};
int main()
{
float time_gap = 10.0;
int count_gap = 10;
unordered_map<string, queue<MALICE>> umap;
//初始化
int a = 0, b = 0, c = 0, d = 0;
int max_num = 4;
while (true)
{
queue<MALICE> malice;
malice.push(MALICE(0.0, 0));
string temp = to_string(a) + "." + to_string(b) + "." + to_string(c) + "." + to_string(d);
umap.insert(make_pair(temp, malice));
d += 1;
if (d > max_num)
{
d = 0;
c += 1;
if (c > max_num)
{
c = 0;
b += 1;
if (b > max_num)
{
b = 0;
a += 1;
}
if (a > max_num)
break;
}
}
}
//新来的访问
umap["0.0.0.0"].back().count = 10;
float time = 5;
string ip = "0.0.0.0";
while (time - umap[ip].front().time >= time_gap)
{
umap[ip].pop();
}
if (umap[ip].size() == 0)
{
umap[ip].push(MALICE(time, 0));
}
else
{
if (time - umap[ip].front().time < time_gap)
{
umap[ip].push(MALICE(time, umap[ip].back().count + 1));
if (umap[ip].back().count > count_gap)
{
umap[ip].back().count = 0;
cout << "malice ip:" << ip << endl;
}
}
}
return 1;
}
好未来:
1面,主要还是聊项目经验。实际遇到的问题。
笔试,快排的思想讲解,不需要写代码。
其他题型:
题目1:
给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。
示例 1:
输入: coins = [1, 2, 5], amount = 11
输出: 3
解释: 11 = 5 + 5 + 1
示例 2:
输入: coins = [2], amount = 3
输出: -1
说明:
你可以认为每种硬币的数量是无限的。
int coinMinWays(vector<int>& coins, int amount) {
vector<int> dp(amount+1, amount+1);
dp[0] = 0;
for (int i = 1; i <= amount; ++i) {
for (int j = 0; j < coins.size(); ++j) {
if (coins[j] <= i) {
dp[i] = min(dp[i], dp[i - coins[j]] + 1);
}
}
}
return (dp[amount] > amount) ? -1 : dp[amount];
题目2:
有1,2,5,10等不同零钱各若干,问如果要组合成N元,有多少种不同的组合方式?假设有m种零钱,具体面值存在arr中,要找的钱为n。
例如:arr=[1, 2, 5, 10], n=5, 则有4种组合方式,分别为:
1,1,1,1,1
1,1,1,2
1,2,2
5
提示:不需要给出具体的组合,只需要找出组合的数量
int countWays(vector<int>&coins, int amount) {
vector<int> dp(amount+1 , 0);
dp[0] = 1;
for (int i = 0; i < coins.size(); ++i){
for (int j = coins[i]; j <= amount; ++j){
dp[j] = (dp[j] + dp[j - coins[i]]);
}
}
return dp[amount];
}
int main() {
vector<int> coins;
coins.push_back(1);
coins.push_back(2);
coins.push_back(5);
coins.push_back(10);
int amount = 5;
cout << coinMinWays(coins, amount) << endl;
cout<<countWays(coins, amount) << endl;
}
题目3,
取1000w正整数的前100个输出。
思路,堆排序,
bool compare(int a, int b)
{
return a > b;
}
int main()
{
int MAX_NUM = 10;
int pre_num = 5;
int input;
vector<int> small_top_heap;
int index = 0;
while (cin >> input)
{
small_top_heap.push_back(input);
index += 1;
if (index == pre_num)
{
make_heap(small_top_heap.begin(), small_top_heap.end(), compare);
}
if (index > pre_num)
{
push_heap(small_top_heap.begin(), small_top_heap.end(), compare);
pop_heap(small_top_heap.begin(), small_top_heap.end(), compare);
small_top_heap.pop_back();
}
if (index >= MAX_NUM)
break;
}
sort_heap(small_top_heap.begin(), small_top_heap.end(), compare);
for (int i = 0; i < small_top_heap.size(); i++)
cout << small_top_heap[i] << " ";
cout << endl;
return 0;
}
tf.summary.scalar用来显示标量信息
tf.summary.histogram一般用来显示训练过程中变量的分布情况
tf.summary.distribution分布图,一般用于显示weights分布
tf.summary.text将文本类型的数据转换为tensor写入summary中
tf.summary.image输出图像
tf.summary.audio展示训练过程中记录的音频
tf.summary.merge_all
tf.summary.FileWriter指定一个文件用来保存图
最后,分享一下本人的leetcode笔记。
想想来北京3年了,从最开始的不被认可,被钓鱼,到现在,感觉收货也蛮多的,至少到现在还是得到好多公司的认可。有时候收了别人的offer最后又拒绝了别人,心里也挺难过的。最后感谢一下,曾经认可自己的公司和人。
其他建议:
(1)明确目前阶段的自己最需要的是什么。是镀金,是money,是带团队经验,是提升自己能力,是安稳......,在没有一个offer满足所有优点的时候,选择自己最需要的那个。
(2)寒冬中的跳槽,无非是从一个坑到另一个坑。很多时候,从脉脉上得到的消息,你会感觉所有你面上的公司都有负面新闻。这时候就根据自己的面试感受做选择了。做到,既来之,则安之。
(3)还有一个感触就是,在AI算法这方面,每年都有好多新的东西更新,知识保值性太差了。新人永远比老人有优势。想想当年这个时候的自己,和现在的应届生比,差距确实很大。或许这就是知识进步太快了。就好比,从SVM提出,到第一个程序实现,中间经历了好长时间,那个年代就没有牛人吗?但是,现在面试应届生,随便都可以将SVM说个很不错。牛顿穷其一生发现了3个定律,现在的学生,也许不需要一学期就都学会了。爱迪生,特斯拉,瓦特......泡沫终将退去,也许在算法和工程的抉择中,工程才是最终的胜利者。
后记:
鲁迅说过,人只要又钱,烦恼就会减掉90%以上,情商和智商也会提高,更不会乱发火。钱从哪里来,鲁迅没说,但是,褚老说了,