微信公众号:Jerry的算法和NLP
| 题目1 圆形花园的入口
小区花园里有n个入口,现在要修一些路,要求每个入口只能有一条路,且每条路之间互不相交,求输入为n的时候有几条路
| examlple:
| 分析:
这道题目主要考察的知识点为动态规划
动态规划主要就是要找准它的转移方程和base case以及目标
题目中提到,N是一个输入为2-1000的偶数
先找base case:
N=2 dp[2]=1 只有一条路 那么只有一种情况 这个好理解
N=4 dp[4]=2
N=6 dp[6]=5
当N=8的时候,怎么分析?
现在把每个门都标上了号码牌,我们假设我们从1开始看。
1一开始可以和 2或者 8 相连,那么剩下了6个门,那么剩下六个门连通的可能总数为dp[6](前面已经计算了)
1可以和7相连吗?不可以,因为这样8无论如何都会使得他们相交
所以我们必须隔两个门取。
1接下来和 2+2=4 或者 8-2=6 相连 当1和4相连的时候 剩下的六个门组合为dp[2]*dp[4]
此时 1 再和 4+2=6 或者 6-2=4 相连 此时已经发生了重复计算的情况,设置好跳出条件即可
| 总结
先锁定一个门(假设为1),从两端开始 先和距离为1的门相连,然后距离为3 距离为5直至发生重复计算跳出循环
或者从一端开始直至绕了一圈回到1这个门的时候跳出循环
| Python代码
1a=int(input())
2dp=[0 for i in range(a+1)]
3dp[0]=0
4dp[2]=1
5dp[4]=2
6dp[6]=5
7for i in range(8,a+2,2):
8 for j in range(i-2,0,-2):
9 if j<i-j-2:
10 break
11 else:
12 if j==i-2:
13 dp[i]+=dp[i-2]*2
14 elif j==i-2-j:
15 dp[i]+=dp[j]*dp[j]
16 else:
17 dp[i]+=dp[j]*dp[i-2-j]*2
18print(dp[a])
| 题目2 2048的操作
2048游戏是一个44的矩阵,用户可以按上下左右4个方向键让所有的方块向同个方向运动,两个相同数字方块撞一起之后合并成为他们的和,每次操作之后随机生成个2或者4合并规则:相邻会撞的两个数字合并且一个位置只会触发一次合并,且优先合并移动方向顶部的位置
比如【2,2,2,2】合并后【0,0,4,4】
【0,2,2,2】合并后【0,0,2,4】
输入第一行是用户按下的方向键,1代表上,2代表下,3代表左,4代表右接下来是一个44的矩阵,空格分割,0代表该位置没有数字
| 分析
这个题目其实就是考察对边界条件的判定和对两数之间的值是否相等的判定
python 代码
1com = int(input())
2l=[]
3for _ in range(4):
4 l.append(list(map(int,input().split())))
5
6if com == 1:
7 for i in range(3, 0, -1):
8 for j in range(4):
9 if l[i-1][j] == l[i][j]:
10 l[i][j] = 0
11 l[i-1][j] *= 2
12
13 for k in range(3, 0, -1):
14 if l[k-1][j] == 0 and l[k][j] != 0:
15 l[k-1][j] = l[k][j]
16 l[k][j] = 0
17 if l[k-1][j] == l[k][j]:
18 l[k-1][j] *= 2
19 l[k][j] = 0
20
21elif com == 2:
22 for i in range(0, 3, 1):
23 print(i)
24 for j in range(4):
25 if l[i + 1][j] == l[i][j]:
26 l[i][j] = 0
27 l[i + 1][j] *= 2
28
29 for k in range(0, 3, 1):
30 if l[k + 1][j] == 0 and l[k][j] != 0:
31 l[k + 1][j] = l[k][j]
32 l[k][j] = 0
33 if l[k + 1][j] == l[k][j]:
34 l[k + 1][j] *= 2
35 l[k][j] = 0
36elif com == 3:
37 for i in range(4):
38 print(i)
39 for j in range(3, 0, -1):
40 if l[i][j - 1] == l[i][j]:
41 l[i][j] = 0
42 l[i][j - 1] *= 2
43
44 for k in range(3, 0, -1):
45 if l[i][k - 1] == 0 and l[i][k] != 0:
46 l[i][k - 1] = l[i][k]
47 l[i][k] = 0
48 if l[i][k - 1] == l[i][k]:
49 l[i][k - 1] *= 2
50 l[i][k] = 0
51
52elif com == 4:
53 for i in range(4):
54 print(i)
55 for j in range(0, 3, 1):
56 if l[i][j + 1] == l[i][j]:
57 l[i][j] = 0
58 l[i][j + 1] *= 2
59
60 for k in range(0, 3, 1):
61 if l[i][k + 1] == 0 and l[i][k] != 0:
62 l[i][k + 1] = l[i][k]
63 l[i][k] = 0
64 if l[i][k + 1] == l[i][k]:
65 l[i][k + 1] *= 2
66 l[i][k] = 0
67
68for i in range(4):
69 print(" ".join(map(str, l[i])))
后记
2020大厂笔试 | 网易提前批(1)
2020大厂笔试 | 网易提前批(2)
2020大厂真题 | 腾讯笔试
背包九讲(1)0/1背包问题
背包九讲(2)完全背包问题
数据结构类题目
- LinkedList
- 003-从尾到头打印链表
- 014-链表中倒数第k个结点
- 015-反转链表
- 016-合并两个或k个有序链表
- 025-复杂链表的复制
- 036-两个链表的第一个公共结点
- 055-链表中环的入口结点
- 056-删除链表中重复的结点
- Tree
- 004-重建二叉树
- 017-树的子结构
- 018-二叉树的镜像
- 022-从上往下打印二叉树
- 023-二叉搜索树的后序遍历序列
- 024-二叉树中和为某一值的路径
- 026-二叉搜索树与双向链表
- 038-二叉树的深度
- 039-平衡二叉树
- 057-二叉树的下一个结点
- 058-对称的二叉树
- 059-按之字形顺序打印二叉树
- 060-把二叉树打印成多行
- 061-序列化二叉树
- 062-二叉搜索树的第k个结点
- Stack & Queue
- 005-用两个栈实现队列
- 020-包含min函数的栈
- 021-栈的压入、弹出序列
- 044-翻转单词顺序列(栈)
- 064-滑动窗口的最大值(双端队列)
- Heap
- 029-最小的K个数
- Hash Table
- 034-第一个只出现一次的字符
- 图
- 065-矩阵中的路径(BFS)
- 066-机器人的运动范围(DFS)
- 具体算法类题目
- 斐波那契数列
- 007-斐波拉契数列
- 008-跳台阶
- 009-变态跳台阶
- 010-矩形覆盖
- 搜索算法
- 001-二维数组查找
- 006-旋转数组的最小数字(二分查找)
- 037-数字在排序数组中出现的次数(二分查找)
- 全排列
- 027-字符串的排列
- 动态规划
- 030-连续子数组的最大和
- 052-正则表达式匹配(我用的暴力)
- 回溯
- 065-矩阵中的路径(BFS)
- 066-机器人的运动范围(DFS)
- 排序
- 035-数组中的逆序对(归并排序)
- 029-最小的K个数(堆排序)
- 029-最小的K个数(快速排序)
- 位运算
- 011-二进制中1的个数
- 012-数值的整数次方
- 040-数组中只出现一次的数字
- 其他算法
- 002-替换空格
- 013-调整数组顺序使奇数位于偶数前面
- 028-数组中出现次数超过一半的数字
- 031-整数中1出现的次数(从1到n整数中1出现的次数)
- 032-把数组排成最小的数
- 033-丑数
- 041-和为S的连续正数序列(滑动窗口思想)
- 042-和为S的两个数字(双指针思想)
- 043-左旋转字符串(矩阵翻转)
- 046-孩子们的游戏-圆圈中最后剩下的数(约瑟夫环)
- 051-构建乘积数组
剑指offer刷题交流群
扫码添加微信,一定要备注研究方向+地点+学校+昵称(如机器学习+上海+上交+汤姆),只有备注正确才可以加群噢。
▲长按加群