前言
今天聊聊掌握了不一定能拿到大厂 Offer,但不掌握一定进不去大厂的神技「数据结构与算法」。
为什么突然提到了数据结构与算法呢?这要从一个朋友的吐槽开始。
我这位朋友一心想进大厂,学历还不错、能力也不错,但就是拿不到大厂Offer。大家都劝他多刷 LeetCode ,把数据结构与算法弄明白。他确实听了,半年过去之后,现在基础知识还行,一旦涉及图、排序、递归这些高级一点的知识就完蛋了。
其实很多人都有遇到这种情况,算法到底有多重要呢?
数据结构与算法是互联网大厂的敲门砖,也是开发者精益求精、持续提升的内功基础。
面试为什么考算法?
无非是算法最能说明一个人的综合实力。
而大厂考算法一般也会分两步,第一步:让你直接说思路;第二步:让你实操写代码。
通过这两步,就可以看出你的编程内功是否深厚,除此之外还能多维度考察你的其他能力,比如:逻辑思维清晰与否、debug 能力如何、编码习惯怎样、是否能写出可维护的代码等等......
下面讲一讲算法的学习方法
第一部分:把“烂”代码优化为高效率代码的方法和路径,也是关于代码开发与优化方法框架的总纲。代码的目标,除了完成任务,还要求把某项任务高效率地完成。
第二部分,补充必备的数据结构基础知识。时间/空间复杂度的降低,要求对数据有超强的组织方式,这些能力需要你对数据结构的基础知识有极为深刻的理解,只有理解了他们的优劣才能灵活选用合适的数据结构。
第三部分,这部分是你学习的重点,也就是用算法思考问题的逻辑和程序设计方法。
第四部分,侧重在 BAT 高频面试真题详解。
第五部分,面试现场。很多工程师有个共性问题,那就是明明有能力,却说不出来,表现得就像是个初学者一样。
其中,最最最重要的就是刷题了,百炼才能成钢!!(重要的事儿多说几遍。)
推荐几个做编程题目的网站:
下面给大家分享一些算法题
题目:
在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
分析:
根据题意画了个简单的图,首先我们要确定查找开始的位置,因为它是二维的数组,它的下标变化是两个方向的,根据四个边界点来分析。
a b
c d
A:向下 增 ,向右 增
B:向左 减 ,向下 增
C:向上 减 ,向右 增
D:向左 减 ,向上 减
可以看出从B 或C点开始查找刚好可以构建一个二叉查找树。
二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。
先确定二维数组的行数和列数,把 查找值 与 二叉查找树的根节点(B或者 C)开始比较,如果相等返回true,小于查找左子树,大于就查找右子树。如果遍历超过数组边界,就返回 false。
以C为根节点查找
public class Solution {
public boolean Find(int [][] array,int target) {
int i = array.length -1;
int m = array[0].length -1;
int j = 0;
while(i>=0 && j<=m){
if(target == array[i][j]){
return true;
}else if(target >array[i][j]){
j++;
}else{
i--;
}
}
return false;
}
}
以B为根节点查找
public class Solution {
public boolean Find(int [][] array,int target) {
int i = array.length -1;
int j = array[0].length -1;
int n = 0;
while(j>=0 && n<=i){
if(target == array[n][j]){
return true;
}else if(target >array[n][j]){
n++;
}else{
j--;
}
}
return false;
}
}
输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
题目分析
解法一 运行时间:29m 占用内存:629k
public int NumberOf1(int n) {
String s=Integer.toBinaryString(n);
char[] c=s.toCharArray();
int j=0;
for(int i=0;i<c.length;i++){
if(c[i]=='1'){
j++;
}
}
return j;
}
}
解析:
public static String toBinaryString(int i)
以二进制(基数 2)无符号整数形式返回一个整数参数的字符串表示形式。
①先把整数转换成二进制字符串
②把字符串转换成字符数组
③遍历该数组,判断每位是否为1,为1 计数加1。
④遍历完成返回1的个数
解法二 运行时间:30ms 占用内存:629k
public class Solution {
public int NumberOf1(int n) {
int count =0;
while(n!=0){
count++;
n = n&(n-1);
}
return count;
}
}
解析:
如果一个整数不为0,那么这个整数至少有一位是1。如果我们把这个整数减1,那么原来处在整数最右边的1就会变为0,原来在1后面的所有的0都会变成1(如果最右边的1后面还有0的话)。其余所有位将不会受到影响。
题目:
用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
思路:
压入元素直接压入stack1 删除元素先查看stack2是否为空,非空则弹出;空则将stack1中元素取出,置于stack2中
代码:
public class StackQueue {
Stack<Integer> stack1 = new Stack<Integer>();
Stack<Integer> stack2 = new Stack<Integer>();
public void push(int node){
stack1.push(node);
}
public int pop(){
if(stack2.empty()){
while(!stack1.empty())
stack2.push(stack1.pop());
}
return stack2.pop();
}
递归和迭代的区别是什么,各有什么优缺点?
程序调用自身称为递归,利用变量的原值推出新值称为迭代。
递归的优点大问题转化为小问题,可以减少代码量,同时代码精简,可读性好;
缺点就是递归调用浪费了空间,而且递归太深容易造成堆栈的溢出。
迭代的好处就是代码运行效率好,因为时间只因循环次数增加而增加,而且没有额外的空间开销;
缺点就是代码不如递归简洁
找不到学习资料怎么办
有很多小伙伴他们其实都明白算法的重要性,也有去学习的心,可是苦于不知道从何处下手,身边也没有可以请教的人。
下面我就介绍一下我整理的学习资料。