12人加入学习
(0人评价)
算法面试必备数据结构和算法
价格 $9,999美元
该课程属于 2023.7.9 CS课程 请加入后再学习

例题:25min

 insert Delete GetRandom.  类似API的设计

getRondom的话可以用math.random的方法。

hashmap,+array_list. 

但还有问题,重复加入怎么办,可以用val:list<indexs>

通常design的题要用更多的data structure去实现

 

例题 :Longest Duplicate substring.47min

我的一点想法:既然重复,那么可以直接双pointer,看字母是否重复,有重复的话,计算substring长度,然后两个起点开始substring check就可以。但是abacabac的话不太实用。

hahsset的用较大一点的质数

nlogn算法。 比如说(0,5)(1,6),(2,7)这些遍历,如果没有就说明siez太大,然后检测size/2,检查(0,2)(1,3),。。。如果有的话,检查上稍大一点,(0,3),(1,4).。

 

 

hashmap和hashset的区别,有collision?

 

 

  • Treemap

 

Treemap红黑树,可以让key按照顺序排列,hahsmap不行 。用的是BST

C++有么????map好像就是。Hashmap的好像是unorder_map的实现

 

complete tree: 所有层数除了最后装满,最后层数尽可能向左靠。(底层实现heap的一个用法)

 

 

例题:longest continuous subarray with absolute diff less than or equal to limit

 

brute force:for for确定subarray,内部还得两两对比,或者最大值或者最小值

优化:slidingwindow+treemap找最值(logn)如果>limit,移动左窗口,并且treemap.remove(num[left])

而且treemap{val:{indexs可能重复}},index要去掉最前面的,不存index的话找不到谁最先。比如remove 2:[2,3,5],要是i=2的会把3和5的去掉,这样就导致后面的误判。

也可以用stack或者queue去优化,比如用global的量去存max差别?

 

例题:1h53min Data Stream as Disjoint intervals.

treemap ,找最值,最小的最大数和最小的最大数2h10min. key:value 就是low bound和high  bound,注意相连的合并情况 [1,2]和[4,5]插入3就变成[1,5]。

[展开全文]
  • HashMap和Hashtable的区别

Map interface.

Allow NULL(key);

unsynchronized.

not ordered。 eg:  2%16=2.  1%16=1,先存进去的数不一定排在前面。

底层都是array

 

  • Hashfunction

选择质数,不然可能有公约数导致hash confliction。 

 

有hash confilct的话:

Separete chaining.可以用链表(linklist)连接起来所有同hash value的node。(主要记忆即可)。优化方向还可以是BST(访问时间logn)

或者Linear probing:当前confict,找到下一个,直到找到空位。 但是可能效率比较低。

Double Hashing: 发现conflict, 用secondary hash、

 

  • rehash,根据load effector。

 

常见题型

  1. sliding window
  2. 利用hash思想去重,赵duplicate,0(1)时间查找
  3. 有关cache的设计题

 

解题思路,一开始没想法先找brute force的复杂度,然后想办法优化。

例题: contain Duplicates. 利用hashmap(num[i],i),然后用一个pointer代表尾部, find有无相同,然后判断index是不是前面k长度以内的。 也可以put value的时候判断之前最近的index是哪个,然后更新掉value,index的pair

也可以排序好,然后用list《node》存储index和value,然后for去判断相邻的==value的index在不在范围内

 

例题48min:longest substring without repeating characters.   

可以用two pointer做法,然后hashmap存Slow和fast中间的字母判重复,然后重复了之后slow直接移动到fast的位置。不用慢慢移动。

 

 

例题:1h2min。 shortest substring contains the all given characters.

brute force。

而且这里hashpmap不能存index,因为"abbbc",s就不能直接跳了,要一点点移动。f是未满足sunstring的时候移动,s是满足的时候移动。

检查hash是否符合的可以用for loop。 也可以用一个global variable match=n; hashmap里面存需要出现的count,出现一次hash里面对应元素-1. 然后match+1.也可以表示是否符合标准,这样就不用for遍历hash了

 

 

例题1h38min: repeated DNA sequences()可以直接把所有10位长度substing存到hash,然后后面判断有没有出现过

还可以用bitmap,A:00,C:01,G:10:,D:11.  hashvalue作为key也可以,substring作为value

 

 

例题:LRU cache:hashmap

linkedlist只能表示加进cache的顺序,但是get(1)不能反映到linklist里面,

queue不行因为移动的不一定是开头和末尾,中间的无法改变。

思路2h17min处:hash存key,node,node是新class

[展开全文]
  • 图 graph
  • 图的基本概念
  • 分类存储
  • 遍历
  • 最短路径算法
  • 最小生成树
  • 例题讲解(对于面试很复杂,所以题量少,)

 

 

  • 图论
  1. 图的组成。顶点+边

vertex:度degree(与他连接的点的个数之和)入度(所有接入该点的边数之和)和出度(outdegree)

边(edge)

 

  • 图的分类

有向图和无向图。

有权图(每条边具有一定的权重(weight))和无权图(无权重或者权=1)。

有环图(如果遍历图的顶点,某个顶点可以被访问超过一次)和无环图(tree)。 (这是有向图的分类)

连通图(任意两个顶点都是连通)和非连通图(存在两个顶点不连通)和完全图(所有顶点和其他顶点是连通的)

 

  • 图的存储方式

n个顶点的图有一个n*n大小的邻接矩阵

一个无权图中1代表两点联通,0代表不连通

有权图中每个元素代表权重,0代表不相连。

无向图中,邻接矩阵关于对角线相等。

 

稠密图适合邻接矩阵,稀疏图适合邻接链表

 

邻接链表:每一个点存储一个链表指向所有与该店直接相连的点。 (增加或者删除复杂度更小)

有权图中链表中的元素值对应着权重

 

 

  • 图的遍历

操作有+-vertex。

DFS:访问顶点v,依次v未被访问的邻接点出发,深度优先遍历,直至途中和v有路径相同的顶点都被访问。使用stack

若此时仍有顶点未被访问,则重新开始DFS

 

BFS:使用queue。从队列中取出一个节点然后直接将所有未检验子节点push到queue中。

可以用来解决最短路径的问题。但是需要存储的信息量很大。 

对于稀疏图来说,DFS容易陷进去最长的一支分路。

但是每一层数量过多,BFS也容易耗时。

 

总体来说,倾向于dfs,内存小,解决问题更多一点

 

例题:lc133. clone graph。42min处 

 

  • 最短路径算法。
  • dijistra算法

适用于非负权值的单源最短路径,斐波那契堆。

使用BFS。

 

  • bellman-ford算法

无负权回路(一个回路的权值相加为负)的图每对节点之间的单源最短路径,并能检测负圈。

  • floyd算法

权值有负的单源最短路径,但不能有负圈回路

  • SPFA算法

有负权值,且欸有负圈的图的单源最短路径。

 

 

LC743 network delay time 1h53min,直接可以用dikistra

Lc787。bellman-ford或者BFS。kstop可以直接停

 

 

  • 最小生成树。
  • kruskal算法,prim算法

kruskal算法,

 

 

 

 

 

 

[展开全文]
  • stack&queue
  • binary tree&binary search tree

stack FILO,先进后出,可以用array implement

queue FIFO,先进先出,可以用linked list implement

Stack:应用:树上的递归DFS改写为iteration

Queue:应用:1.BFS   2. Moving average

 

Moving average. LC 346. Moving Average from Data Stream.   可以用moving window的题目

 

  • 二叉树

单纯的二叉树,一父节点最多两个子节点,没有大小要求。link list也算是一个二叉树。

 

Balanced binary tree:对任一节点来说左右子树的高度差不超过一。

 

二叉搜索树:左边所有节点<=中间<右边所有节点,平均O(logn),看看是不是balanced。

heap不能进行搜索的操作,只能保证插入删除元素时 logn。

 

 

  • 二叉树

二叉树的遍历:可以用recursive

先序,中序,后序遍历。

叶节点的时候return;

preorder先序遍历:中左右

add;  traverse left; traverse right

inorder中序遍历:左中右。

traverse left;    add;    traverse right;

postOrder后序遍历:左右中 

traverse left; traverse right; add;

可以 go through一些树的list

 

  • 遍历法(traversal)vs分治法

遍历法:依次遍历所有节点,遍历中做记录,对节点进行操作。每个结点的最大深度是上一次最大深度和当前深度的最大值,递归时当前深度+1。 可以用全局变量。 而且可能需要另加一个helper function来记录遍历中的cur_深度

 

分治法:先让左右子树去解决同样的问题,然后得到结果后在整合为整棵树的结果.一个结点的最大深度=左右儿子最大深度+1

 

例题:LC104. Maximum depth of binary tree.

 

 

例题:lc110: balanced binary tree。 细节,子树汇报的时候可以不只汇报height,还可以汇报boolean的balanced,或者用height-1来表示unbalance。因为,最下面子树不balance但是root仍有可能会判断为balance。

recursive经常写helper function,因为i可能return的value或者input可能不一样。

 

用stack表示inorder tranversal。without recursion。有个网站写了逻辑。

 

 

例题:LC173Binary search Tree iterator. 1h41min处

Lc98 validate BST。 1h42min。  可以用stack 来iterate tree,因为iprin出来的值一定是从小到大(BST)。

也可以用recursion来判断

BST上面的inorder tanversal一定是从小到大

 

 

LC938 range sum of BST. 可以用DFS和全局变量,recursive implement ation 。 2h00min

 

LC114. faltten binary tree to lined list. 2h4min. 遍历法可以,分治法,从下往上

 

作业:binary tree paths。

 

 

[展开全文]

Lc873.length of longest fibonacci subsequence

 

back_trakcing   and recurrsive

dynamic programming:得到一个递归表达式

 

 

36:29 dp做法

 

作业:Lc1414. find the minimum number of fibonacci numbers whose sum is k

 

 

recursion 在 merging two sorted list里面怎么用。lc21

 

Lc82 removeduplicates from sorted list II  10min.  在53min处用递归,

Lc 658 Find K closet elements.可以一用heapsort,,

 

Lc 347 top K frequent element;

 

  • quick select

 

Lc215   kth element in an array  可以用heap。也可以quick select

 

Lc973 k closet points to origin

 

LC56  merge interval  例题讲解, stack是啥啊,要先sort

Lc1288 remove covered intervals例题1:30min

lc252 meeting room 1h40min处例题

 

[展开全文]
  • binary search 

在一个已经排好序的数组上,O(logn )复杂度

先找mid=start+end。 array[mid]=val1,然后判断target,val1<target,就向右找,小于则向左找。重复上述过程, mid2=(end+mid)/2只取整数。

 

写一些函数的时候,先判断input是不是null或length==0?

某些情况下比如while(start+1<end)的话要单独判断end和start是不是target

为什么不是start<end退出,比如下面的例子,找最后一个出现的位置。【2,2】

while(start<end){

   mid=(0+1)/2=0;

if (mid==target){  start =mid;}

}

应该用相邻或相等退出,即start+1<end;

求最后出现的位置: if找到了就向右找,

而且也要先判断end==target

第一个出现的位置,if找到了就向左找。

而且要先判断start==target。

 

而且mid= start+(end-start)/2 更不容易overflow,算是一个小的优化

 

模板:

while (start+1< end){

          mid=start+(end-start)/2;

         if(num[mid]==target)  {return mid}

         else if(  >){  end=mid}

         else{   start=mid }

        if start==target 

       if end==target.

}

 

 

推荐写一些子 函数维持宏观框架

 

 

例题: find K closet elements

思路: 可以先bSearch找到target,然后双指针两边走

先看输出类型,新建好。

然后先写出思路, 然后把子程序的接口写出来,定义出来,input和output,然后写出来子函数的作用:output是什么

 

 

  • Heap

大顶堆和小顶堆,min-heap和max-heap。

每一个node满足:father>=childs (max)

                           father<=childs(min)

左右没有关系

 

binary heap representation:

  现在node为A【i】,

Arr[(i-1)/2] is the parent node.

Arr[2i+1] is the left child

Arr[2i+2] is the right child

 

复杂度:getMini() :对于Min-heap是一个O(1)

extractMin(): remove the root ,O(logn)

insert(): O(logn)

delete(): O(logn)

 

 

  • 重点!!!!!
  • top K的题右3solution
  1. sort O(nlogn) 不是很好
  2. quick select. (on avarge O(n)),有时候快有时候慢。要求是要进行该方法,必须已经拿到全部的数据,万一新来的data,只能重新来一遍
  3. Heap O(nlogk),只需要size 为k的heap, insert 每一次都是logk,然后比n次,现实生活中k远小于n。更适合Stream data,可以适用于新来的data,新来一个数是O(logk

例题:Kth largest element要用min-heap,因为和root比较,小的就不用insert,大的菜肴insert进去,因为,heap里面村的是k个最大的,

步骤:先建立一个k size的heap,直接加进去,然后对比,如果大于,则pop root之后push(元素 )

[展开全文]

现在大体框架,子函数可以先用名字代替,最后再写

 

sort:

  • 冒泡,选择,插入 O( n^2)
  • 归并,快速,堆 O(nlogn)
  • 桶,基数,计数,O(n)

 

 

  • 冒泡排序

比较相邻的元素,然后交换,大的后移,对所有的元素移动排序,两个for

优化,如果发现某个元素不用移动,可以提前退出内部for循环,说明已经对他来说已经排完了。但注意 23401这种情况看看

 

  • 选择排序

找最小,放在起始位置,然后后面的在找最小,然后跟第二位置交换,以此类推

 

  • 插入排序

两个序列,扫描未排序序列,然后往前比较,然后插入到对应的有序序列的对应位置,知道所有未排序序列都被扫描

 

  • 希尔排序

不稳定排序,优先比较距离远的元素,然后逐渐缩小增量比较,对于插入排序改进,选择增量序列k,按照k的个数进行k躺排序,每趟排序,根据对应增量,分割成子序列然后分别插入排入。

 

 

Divide and conquar

  • merge sort

把已经排好序的子序列合并。n->n/2和n/2->各自分成两个, 然后分到最小序列,然后一点点合并成最上面,可以用递归算法,但内存消耗比较大,也可以用迭代。分成sort函数和merge函数,在merge时,两个array长度不一定相同,可以用双指针 merge sorted lit,判断一个赋值一个,最后某一个走完之后另一个直接复制到sorted后面

 

  • quick sort

挑出基准量,然后根据这个标准分成左右两边,小在左,大在右,然后不断细分下去,pivot的选择也很重要

 

  • heap sort

类似于二叉树,先创建一个heap,把队首和队尾呼唤,大顶堆和小顶堆,father和child的比较。把heap的尺寸缩小1,然后剩余的元素重新构建大顶堆,然后重复步骤,知道heap的尺寸缩小为1。

 

  • 桶排序 bucket sort

设定一个定量的数组当作空桶,遍历输入数据,并把数据一个一个对应放到桶里,对每个不是空的桶排序,然后从不是空的桶把排好序的数据连接起来。

桶就是一个范围桶,内部进行sort可以merget sort或者其他的也行。  

桶的数量的选择, (max-min)/length+1;

 

  • radix sort 基数排序

适合小范围数

首先取得最大值,并取得位数,然后从最低位开始排序,然后根据10号位拍,然后地推,从最小位开始可以保持每个位数内部的大小关系保持:14》13》12这种在10号位=1的内部,这样就能保持一个稳定的。其实内部的实现也是桶排序,bucket

 

  • 计数排序counting sort

找出max和min,然后统计每一个值为i的元素统计次数,然后存入数组C的第i项。 累加所有的次数(从C中第一个元素开始),反向填充目标数组:将每个元素i放在新数组的第c【i】项,每放一个元素就c[i]-1,类似与从桶中一个一个拿出来连着排放位置。

 

 

heapsort 可以用来找kth 最大或者最小

kth 最值可以quick sort的pivot思路,递归,

one-pass algorithm:只读一次input

sort_color : 4 color, 初始化4个常量。然后发现0,则所有的count+1,因为底部升高,上面全都升高,后面以此类推就可以求次数

H_index?

 

wiggle sort: 找中位数,分成前后两个等长部分,然后穿插安放

Maximum gap: bucket控制至少一个空bucket,这样,bucket内部最大gap=一个bucket长度,但是bucket之间gap却可以》=一个bucket之间

 

[展开全文]
  • Linked list

node{ int val; Node next;}

1->2->5>7>null

可以每次都先设一个dummyhead,return dummy head.next

二叉树: node{ int val; Node left;Node right}

 

Database Index,讲到树的时候会有提

三大基本功:

  1. reverse a link list
  2. merge sorted link list
  3. find the middle node of the linklist

dumy node可以放在开头

  • reverse就是next变成prev,原来的head指向null,原来的尾变head
  • middle 的话,一个for loop就可以找到,按照双指针来,尾部走两个,middle走一个
  • merge two sorted list, 双指针,判大小,然后东一。可以先设一个prehead->a->b,return a就可以。注意判断条件:L1很短,空了之后直接把L2后面接上就好了

 判断link list是不是环(不太会考)

double link list

  • 回文判断,双指针,但注意要回预处理大小写字母,空格字符的处理

 

  • soretd array去重,只能in-place和不能创造新的空间,思路:双指针,尾指针判大小后往后移动最后一个同位素的后面,头指针不动,然后把头指针的next赋值成新的数字,移动head,重复尾指针移动,然后return这个去重list。
     

 

  • 滑动窗口,有一个size的subarray,让他内部元素sum最大,小窍门[a,b,c,d]和[b,c,d,e],sub2只需要sub1-a+e就行

 

  • 3sum=0,但不只一组sum相同的情况,全部return。 先sort,然后如果已经sum>0,那么肯定直接break就行,再往后更大,优化: low increment到不重复的新数,eg,0,0,1, 这里lo跳过后面的0直接到1

 

  • 3 sum closest.   常量:INT_MAX和INT_MIN,看32bit还是64bit,

算法除了写出思路,还要讲出思路(80),还要optimization

[展开全文]
  • array  :可以index赋值

arraylist: 两个都可以表示list。  像是class的样子,只能add加法。

array 和 arraylist接口不一杨

interface和 右边的 object:

eg; List<String> al=new ArrayList<String>

List<String> al2=new LinkedList<String>

举例:

List<String> al=new ArrayList<String>

 al=new LinkedList<String>重新赋值也可以,都是list。

但是

ArrayList<String> al=new ArrayList<String>

 al=new LinkedList<String>就会报错。

所以说左边最好写成List泛用性大点,一种coding习惯。

 

 

可以看tutorial去学习arraylist的具体操作,add change remove 等等和new一个arraylist

 

 

 

 

 

  • Hashmap:  <key,value>,key格式不定

array is a special type of Hashmap:<position, value>

暴力搜索O(e^n),排列组合是n!

eg. a=[2,4,56,7,7,8,7] 

Hashmap:知道key求value:O(1),想知道value-》index,可以create一个hashmap。

hashmap的用法可以网上:new, hashmap.keyset

eg: for (integer key : amap.keyset){} for的一个用法

    for( entry <integer,String> entry: a.entryset){}  每一个entry是《key,value》,重新创造类也可以

 

 

API是什么????get,post,put,delete

用法举例:a.putIfAbsent(key,value),就是如果不存在这个key,就push,也可以用if(a.containKey(key1)) {a.put(key1,value)}。省时用法

hashmap原理:视频 how hashmap works in Java:  www.youtube.com/watch?v=c3RVW#KGIIE  48.52秒。 面试可能会问

 

其实hashmap不是严格O(1),比如和inputsize有关,如果input string很长为n,那就是O(n),如果input长度是一个list,长度n,内部元素长度1,那hashmap长度也是O(1).

以回答时间复杂度是考虑input size

eg. 10万个数,2万个和key1有关(linklist),所以复杂度也算是O(n)。算是实际实现问题

如果用2茶树,O(log(n)),java 8的优化。

 

 

 

  • Two sum面试题

leetcode 刷题,算法面试流程:

1.可以一边问面试官requirement,理解题目意思,

2. walk through examples ,复杂度之类的。

3.还可以问面试官自己的大致思路make sense么

4. 得到认可的话就可以开始coding。

5.还剩余时间的话:

            a.面试官可能会问follow question。(一般不需要codng,给思路就可以)

            b.可能还存在一些bug或者特殊情况没考虑,面试馆可能让你过一遍代码根据example,来debug。但也不一定有bug。

但2,3步可能会占挺多的时间,不要很担心,因为没思路不行

 

思路:

search的方法:sorted list的话可以二分法,o(log(n))   , hashmap: O(1)。

walk through example,自己改一下限制条件然后看看思路怎么样

语法问题忘记了的话可以新开个窗口搜一下或者问一下能不能搜一下用法

2 pointers正方向反方向走O(n^2)

 比如sorted array(小->大),如果add后大于target那么右指针往左走,因为要缩小求和就一个for(i, j=len-i-1;i<j;)就可以了。

for可以两个变量,也可以把一个变量写到外面,因为要考虑左右指针的移动,多以i++,j--可以for内部if判断

也可以用while(i<size && j>=0) if 求和小于target,左pointer右走,大于右pointer左走。等于return

但是不是sorted的话要先做sorted在写思路,一般情况下sort函数O(nlogn)

需知道solution的时间和空间复杂度;  

如果面试官提醒有O(n)那么就不要sort了

看看hashmap

    如果知道元素i和target,那么可以看看能不能找到另外一个差值数在不在里面,看看在哪里,所以要用hashmap(这是思路逻辑而不是知道答案上来就说hashmap

eg.HashMap<Integer, Integer> map=new Hashmap< >(); (可以省略,因为前面写了)

for建立hashmap O(n)

if map.containKey(target-num[i])存在就return,不存在就下一个num[i]   O(N)

空间是O(n),因为有hashmap。牺牲空间换了时间

 

窍门:如果没时间写某个functoin比如binary search,可以写comment和跟面试官说一下,然后不细写

 

  • three sum

固定一个数,然后利用two sum

 

 

作业相似题:

 

 

[展开全文]

授课教师

Yuhan老师

课程特色

视频(9)

学员动态

duoduo99 加入学习
wuhaojia 加入学习
SRT2024 加入学习
贺佳苗 开始学习 Session 1
Yichan 开始学习 Session 1