年份是毕业年份,2021是指2021年毕业,不是2021年面试
1. 分享|2021秋招算法总结1-DFS篇
2. 分享|2021秋招算法总结2-BFS篇
3. 分享|2021秋招算法总结3-链表篇
4. 分享|2021秋招算法总结4-二叉树篇
5. 分享|2021秋招算法总结5-排序算法篇
6. 分享|2021秋招算法总结6-字符串篇
1. 分享|2021届毕业生秋招经验总结1-岗位类别介绍
2. 分享|2021届毕业生秋招经验总结2-如何选择offer
1. 美团金融|安卓客户端|面经|offer|2021届秋招|
2. 拼多多|客户端开发|面经|offer|2021届秋招|
3. 网易云音乐|安卓客户端|面经|offer|2021届秋招|
4. 阿里巴巴|客户端开发|面经|2021届秋招|
5. 花旗银行|软件工程师|面经|offer|2021届秋招|
6. 字节跳动|客户端开发|面经|2021届秋招|
7. 叠纸游戏|客户端开发|面经|2021届秋招|
8. 腾讯|客户端开发|面经|2021届秋招|
9. 360|安卓客户端|面经|offer|2021届秋招|
10. 作业帮|IOS客户端|面经|2021届秋招|
11. 滴滴|安卓客户端|面经|2021届秋招|
12. 百度|IOS客户端|面经|2021届秋招|
13. 快手|客户端开发|面经|2021届秋招|
14. 顺丰科技|安卓客户端|面经|offer|2021届秋招|
1. 内推+校招秋招|美团金融服务平台|多项岗位|北京+上海
动规较难,不适合所有人都学习,但是面试前必须知道一些基础要点。能用动规的题目通常是要求:可行性、方案数和最值。本篇列写一些背包问题及其对应的力扣中的题目,还有一些简单中等的动规常见题和系列套题。
本篇整理比较功利性(面试前必备题),如果大家对动规及其解题思路特别感兴趣的话,建议去leetbook看动态规划精讲,以下是链接
比较尴尬的是这两篇LeetBook是力扣PLUS会员专属,仅供会员免费借阅,我学了第一篇的部分内容,没学完时候会员就过期了,但是认识写这两篇的作者,他整理的都很用心,作者力扣主页:FennelDumplings。此处打个没收钱的广告,如果是学生的话,可以去看看力扣针对学生的365天365元的优惠活动,我当时花了79元才充了一个月,后面才发现有这个优惠(然而用不到了,相当尴尬)。充不充取决于自己吧,我就觉得挺省钱的顺口一推罢了。
顺便吐槽一下,我出这个系列就不是为了复制别人的题解啊,只是把相似题目整理下,方便大家刷和知道怎么提升罢了,不需要就关啊,还浪费时间点踩,很让我费解。
推荐大家去搜一下背包9讲,我是通过这个入门的,接下来的整理只包括01背包、完全背包和多重背包,其他的自行搜索或者看我的笔记。因为力扣放外来链接会被和谐,所以考验大家检索能力的时候到了。教学视频可以看看某站,文字信息可以看看某博or某开源代码库,背包9讲的原型题及其代码可以看某a开头的辅导班对应题库或者某l开头的辅导班对应题库(力扣只有变型题)。
描述:有N件物品和一个容量为V的背包。第i件物品的体积是v[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
以下列举两种写法,实际上写法可以微调的,自己探索吧。
原型题方法1:适用于数据量比较小的时候
import java.util.Scanner;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int V = sc.nextInt();
int[] v = new int[N];
int[] w = new int[N];
for (int i = 0; i < N; i++){
v[i] = sc.nextInt();
w[i] = sc.nextInt();
}
System.out.println(maxValue(N, V, v, w));
}
private static int maxValue(int N, int V, int[] v, int[] w){
if (N == 0 || V == 0) return 0;
int[] dp = new int[V+1];
for (int i = 0; i < N; i++){ // 外循环从0开始递增
for (int j = V; j >= v[i]; j--){ // 内循环从V开始递减
dp[j] = Math.max(dp[j], dp[j-v[i]] + w[i]);
}
}
return dp[V];
}
}原型题方法2:适用于数据量比较大的时候
import java.util.Scanner;
import java.util.ArrayList;
public class Main{
static class ValueHolder{
int v,w;
public ValueHolder(int v, int w) {
this.v = v;
this.w = w;
}
}
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int V = sc.nextInt();
int[] v = new int[N];
int[] w = new int[N];
for (int i = 0; i < N; i++){
v[i] = sc.nextInt();
w[i] = sc.nextInt();
}
System.out.println(maxValue(N, V, v, w));
}
private static int maxValue(int N, int V, int[] v, int[] w){
if (N == 0 || V == 0) return 0;
int[] dp = new int[V+1];
ArrayList<ValueHolder> list = new ArrayList<>();
for (int i = 0; i < N; i++){ // 外循环从0开始递增
list.add(new ValueHolder(v[i], w[i]));
}
for (ValueHolder holder : list){
for (int j = V; j >= holder.v; j--){ // 内循环从V开始递减
dp[j] = Math.max(dp[j], dp[j - holder.v] + holder.w);
}
}
return dp[V];
}
}力扣中的变型题
描述:有N种物品和一个容量为V的背包,每种物品都有无限件可用。第i种物品的体积是v[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
原型题方法1:适用于数据量比较小的时候
import java.util.Scanner;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int V = sc.nextInt();
int[] v = new int[N];
int[] w = new int[N];
for (int i = 0; i < N; i++){
v[i] = sc.nextInt();
w[i] = sc.nextInt();
}
System.out.println(maxValue(N, V, v, w));
}
private static int maxValue(int N, int V, int[] v, int[] w){
if (N == 0 || V == 0) return 0;
int[] dp = new int[V+1];
for (int i = 0; i < N; i++){ // 外循环从0开始递增
for (int j = v[i]; j<= V; j++){ //内循环从v[i]开始递增
dp[j] = Math.max(dp[j], dp[j-v[i]] + w[i]);
}
}
return dp[V];
}
}原型题方法2:适用于数据量比较大的时候
import java.util.Scanner;
import java.util.ArrayList;
public class Main{
static class ValueHolder{
int v,w;
public ValueHolder(int v, int w) {
this.v = v;
this.w = w;
}
}
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int V = sc.nextInt();
int[] v = new int[N];
int[] w = new int[N];
for (int i = 0; i < N; i++){
v[i] = sc.nextInt();
w[i] = sc.nextInt();
}
System.out.println(maxValue(N, V, v, w));
}
private static int maxValue(int N, int V, int[] v, int[] w){
if (N == 0 || V == 0) return 0;
int[] dp = new int[V+1];
ArrayList<ValueHolder> list = new ArrayList<>();
for (int i = 0; i < N; i++){ // 外循环从0开始递增
list.add(new ValueHolder(v[i], w[i]));
}
for (ValueHolder holder : list){
for (int j = holder.v; j <= V ; j++){ //内循环从holder.v开始递增
dp[j] = Math.max(dp[j], dp[j - holder.v] + holder.w);
}
}
return dp[V];
}
}力扣中的变型题
描述:有N种物品和一个容量为V的背包,每种物品都有无限件可用。第i种物品的数量为s[i],体积是v[i],价值是w[i]。求解将哪些物品装入背包可使体积总和不超过背包容量,且价值总和最大,输出最大价值。
原型题方法1:适用于数据量比较小的时候
import java.util.Scanner;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int V = sc.nextInt();
int[] v = new int[N];
int[] w = new int[N];
int[] s = new int[N];
for (int i = 0; i < N; i++){
v[i] = sc.nextInt();
w[i] = sc.nextInt();
s[i] = sc.nextInt();
}
System.out.println(maxValue(N, V, v, w, s));
}
private static int maxValue(int N, int V, int[] v, int[] w, int[] s){
if (N == 0 || V == 0) return 0;
int[] dp = new int[V+1];
for (int i = 0; i < N; i++){ // 第一重循环从0开始递增
for (int j = V; j >= 0; j--){ //第二重循环从V开始递减
for (int k = 0; k <= s[i]; k++){ //第三重循环从0开始递增
if (j >= k * v[i]) { // 判断容量是否足够
dp[j] = Math.max(dp[j], dp[j - k * v[i]] + k * w[i]);
}
}
}
}
return dp[V];
}
}原型题方法2:适用于数据量比较大的时候【二进制】
import java.util.Scanner;
import java.util.ArrayList;
public class Main{
static int MAX = 101;
static class ValueHolder{
int v,w;
public ValueHolder(int v, int w) {
this.v = v;
this.w = w;
}
}
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int V = sc.nextInt();
int[] v = new int[N];
int[] w = new int[N];
int[] s = new int[N];
for (int i = 0; i < N; i++){
v[i] = sc.nextInt();
w[i] = sc.nextInt();
s[i] = sc.nextInt();
}
System.out.println(maxValue(N, V, v, w, s));
}
public static int maxValue(int N, int V, int[] v, int[] w, int[] s){
if (N == 0 || V == 0) return 0;
int[] dp = new int[V+1];
ArrayList<ValueHolder> list = new ArrayList<>();
for (int i = 0; i < N; i++){
int cnt = s[i];
for (int k = 1; k < cnt; k *= 2){
cnt -= k;
list.add(new ValueHolder(v[i] * k, w[i] * k));
}
if (cnt >= 0) {
list.add(new ValueHolder(v[i] * cnt, w[i] * cnt));
}
}
for (ValueHolder holder : list){
for (int j = V; j >= holder.v; j--){
dp[j] = Math.max(dp[j], dp[j - holder.v] + holder.w);
}
}
return dp[V];
}
}原型题方法3:适用于数据量比较大的时候【单调队列】
代码非本人撰写,原链接【如被和谐,请自行搜索】:https://www.***.com/solution/content/16038/
import java.util.*;
public class Main{
static int MAX = 101;
static class ValueHolder{
int v,w;
public ValueHolder(int v, int w) {
this.v = v;
this.w = w;
}
}
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int V = sc.nextInt();
int[] v = new int[N];
int[] w = new int[N];
int[] s = new int[N];
for (int i = 0; i < N; i++){
v[i] = sc.nextInt();
w[i] = sc.nextInt();
s[i] = sc.nextInt();
}
System.out.println(maxValue(N, V, v, w, s));
}
private static int maxValue(int N, int C, int[] ss, int[] vs, int[] qs) {
int[] dp = new int[C+1];
Deque<int[]> dq = new LinkedList<>();
int ws = 0; // window start index
int we = 0; // window end index
for (int i=0; i<N; i++) {
int s = ss[i], v = vs[i], q = qs[i];
for (int k=0; k<s; k++) { // loop s slices
dq.clear();
ws = we = k;
for (int j=k; j<=C; j+=s) { // increment each slice by s
if ((we-ws)/s == q) { // slide window already max out
if (dq.size() > 0 && dq.peekFirst()[0] == ws) { // if window start already the max, will eject it
dq.removeFirst();
}
ws+=s;
}
int m = (j-k)/s; // multiplier
while (!dq.isEmpty() && dq.peekLast()[1] <= dp[j]-m*v) { // try to add the current index
dq.removeLast();
}
dq.addLast(new int[]{j, dp[j]-m*v});
we=j;
dp[j] = dq.peekFirst()[1]+m*v;
}
}
}
return dp[C];
}
}提升:把完全背包的题目加上数量限制就是多重背包的题目了。
public class Solution {
public int JumpFloorII(int target) {
return (int) Math.pow(2,target-1);
}
}经典必做系列,具体题目不放了,只写区别。
高频改造题,把鸡蛋改成任意物品(比如手机),就是道新的笔试题了。
高频改造题,搞不懂有这智商为啥去打家劫舍。
很多乱七八糟的,只列举前两题,注意找规律。
虽然是困难,但笔面试出现频率较高
虽然是困难,但笔面试出现频率较高
笔试经常遇到会议室题目的改造,但很尴尬的是它们都是会员题,会员题不放题目了。思路是前缀和,动态规划精讲(一)中有这个专题。
笔试经常用这些题目进行改造。如果面试时候想用贪心的话,要说清楚为什么这题可以用贪心,说不清楚的话还是其他方法吧。这边的题目别纠结难度了,对初学者来说都不简单。
动规题目太多了,我尽量把我笔记里面觉得 眼熟 的题目都列举出来了。如果和我一样的普通面试者(没有算法基础,只为了找工作,不面算法岗),可能面试遇到动规的概率不大(本人自己的面试好像就遇到一次,其他人的也比较少)。但是笔试时候经常会遇到要用动规的题目,此处说的眼熟是笔试、其他人的面经或者群友讨论时候看到过的。