算法岗是地图上色,相邻块颜色不同问题,类似以前奥数的五色地图。递推求公式可解。
###/填坑部分*****/
###题目表述:
一个圆分成n个扇形,用m种颜色上色,要求相邻两个颜色不同。求有多少种不同的方法。
###思路:
首先考虑一些奇怪的临界值
n=1:有m种可能。
n=2:有m(m-1)种可能。
m<2:并且n>2:毫无可能。
然后考虑正常情况
第一个扇面有m种可能,在不考虑最后一个和第一个扇面的颜色关系情况下,后面的n-1块都是有m-1种可能性。但这样得到的可能性是多的,接下来就是要考虑减去第一块和最后一块同色的情况。
当同色时候,其实可以把两个扇面融合,看成一个扇面,这是本题求解的关键。这样减去的部分就可以变成问题参数是(n-1,m)时得到的可能性。
递归表达式出来了:
###S(n,m) = m*(m-1)^(n-1) - S(n-1,m)
其实可以进一步运用高中数学中数列知识,把m看成常数,配一下项,变成等比数列,直接得到最后通式:
###Sn = (-1)^n * (m-1) + (m-1)^n
具体操作不展开了…因为我懒,并且打公式好烦。
代码如下:
#include
#include
using namespace std;
double digui(int n, int m){
if(n==1)
return m;
if(n==2){
if (m<2)
return 0.0;
return (double)m*(m-1);
}
return m*pow(double(m-1), double(n-1))-digui(n-1, m);
}
int main(){
int N, M;
cin >> N >> M;
int ans = 0;
ans=(int)digui(N,M);
printf("%d", ans);
return 0;
}
开发岗是求矩阵最短路径,DP思想,构建状态矩阵可解。
###/填坑部分*****/
###题目表述:
一行方格还是瓷砖n个,有m种颜色可以用来上色,每个格子上色的价格是不同(比如第一个上红色5元,第二个上红色3元)。要求相邻格子的颜色不同情况下,最小花费是多少。
输入格式:
n m
第一格填不同颜色的价格:a b c …(一共m行)
。
。
。
第n格…
比如:
3 3
12 10 8(给第一个格子上色,三种颜色的价格)
6 5 4
9 5 4
###思路:
第一眼以为和算法岗一样,后来仔细一看就发现天差地别。这是经典的DP,状态转移。
找不到题目了,拍照不清楚。。。
大概就是一个矩阵,里面都是正数,然后从最上面走到最下面最小cost是多少这种题目一样,只不过加了一个不能相邻格子走直线而已。
先挂题目
————————————————————————————————————————————————————————
光明小学的小朋友们要举行一年一度的接力跑大赛了,但是小朋友们却遇到了一个难题:设计接力跑大赛的线路,你能帮助他们完成这项工作么?
光明小学可以抽象成一张有N个节点的图,每两点间都有一条道路相连。光明小学的每个班都有M个学生,所以你要为他们设计出一条恰好经过M条边的路径。
光明小学的小朋友们希望全盘考虑所有的因素,所以你需要把任意两点间经过M条边的最短路径的距离输出出来以供参考。
你需要设计这样一个函数:
res[][] Solve( N, M, map[][]);
注意:map必然是N * N的二维数组,且map[i][j] == map[j][i],map[i][i] == 0,-1e8 <= map[i][j] <= 1e8。(道路全部是无向边,无自环)2 <= N <= 100, 2 <= M <= 1e6。要求时间复杂度控制在O(N^3*log(M))。
map数组表示了一张稠密图,其中任意两个不同节点i,j间都有一条边,边的长度为map[i][j]。N表示其中的节点数。
你要返回的数组也必然是一个N * N的二维数组,表示从i出发走到j,经过M条边的最短路径
你的路径中应考虑包含重复边的情况。
——————————————————————————————————————————————————————
题目特别长,加上有点紧张,光是读题目就花了很久的时间。泪流满面谨以此题纪念即将三挂阿里的我。
——————————————————————————————————————————————————————
思路有点类似与求和问题,牛客网上的一道题目https://www.nowcoder.com/practice/11cc498832db489786f8a03c3b67d02c?tpId=85&&tqId=29869&rp=1&ru=/activity/oj&qru=/ta/2017test/question-ranking但不完全一样。有兴趣可以做做。
先挂代码吧。。。
-
package ali;
-
-
import java.util.Scanner;
-
-
public
class zhaolu {
-
public static void main(String[] args) {
-
Scanner input =
new Scanner(System.in);
-
int n = input.nextInt();
-
int m = input.nextInt();
-
long[][] map =
new
long[n][n];
-
for (
int i =
0; i < n; i++) {
-
for (
int j =
0; j < n; j++) {
-
map[i][j] = input.nextLong();
-
}
-
}
-
long[][] res =
new
long[n][n];
-
for (
int i =
0; i < res.length; i++) {
-
for (
int j =
0; j < res.length; j++) {
-
res[i][j] = Integer.MAX_VALUE;
-
}
-
}
-
for (
int i =
0; i < n; i++) {
-
int nowrow = i;
-
int nowcol = i;
-
int distance =
0;
-
solve(nowcol, m, map, res, distance, nowrow);
-
}
-
for (
int i =
0; i < res.length; i++) {
-
for (
int j =
0; j < res.length; j++) {
-
System.out.print(res[i][j] +
" ");
-
}
-
System.out.println();
-
}
-
-
}
-
-
public static void solve(int nowcol, int m, long[][] map, long[][] res, long distance, int nowrow) {
-
if (m ==
0) {
-
if (distance < res[nowrow][nowcol]) {
-
res[nowrow][nowcol] = distance;
-
return;
-
}
-
return;
-
}
-
for (
int nextcol =
0; nextcol < map[
0].length; nextcol++) {
-
if (nowcol != nextcol) {
-
solve(nextcol, m -
1, map, res, distance + map[nowcol][nextcol], nowrow);
-
}
-
}
-
return;
-
}
-
-
}
其实就一个solve函数。
nowrow,记录当前是哪一个出发点,每一行可以对应一个出发点。
nowcol,记录当前走到了哪一个节点。
m,用来记录还需要走多少步。
res,记录最短路径的矩阵
distance,表示当前走的距离
跳出递归的条件是,m==0也就是走完了规定的步数,更改记录的条件是,当前这种走法比以前的走法都要短。
递归过程中下一步是不能与当前位置重合的。
突然发现没什么好讲的了……这题思路并不难,就是参数比较多,处理起来容易出错……
祝大家好运~我再去哭一会儿……
编程题共3道,貌似与其它岗位的小伙伴题目都不一样,本人遇到的难度较低。另外题面包含错别字以及描述不太清晰,值得吐槽。
有一个32位整数n,试找一个最小整数m,使得m的每一位之积等于n,如果找不到这样的整数,输出0
分析可知,整数m的所有位均为2-9的整数,对n做质因数分解变形(每次从9-2取数字做整除),能成功分解证明可以找到合适的整数,然后对分解出来的数字进行排序,从小到大输出,未发现明显trick,1A
-
#include
-
#include
-
#include
-
#include
-
#include
-
#include
-
#define LL long long
-
using
namespace
std;
-
LL m ,n;
-
LL item[
1000];
-
LL cnt;
-
int yinshufenjie(LL num){
-
cnt =
0;
-
LL i;
-
LL temp = num;
-
do{
-
temp=num;
-
for (i =
9;i >=
2 ;i--)
-
{
-
while (num != i)
-
{
-
if (num%i ==
0)
-
{
-
item[cnt++] = i;
-
num = num / i;
-
}
-
else
break;
-
}
-
-
}
-
}
while(temp != num);
-
-
if(num<
10){
-
item[cnt++]=num;
-
return
1;
-
}
-
else{
-
return
0;
-
}
-
}
-
int main()
-
{
-
LL m ,n;
-
cin>>n;
-
if(yinshufenjie(n)){
-
sort(item,item+cnt);
-
for(
int i=
0;i
-
cout<
-
-
}
-
cout<<
endl;
-
}
-
else{
-
cout<<
"0"<<
endl;
-
}
-
return
0;
-
}
第二题 NTES子串判断
水题,判断是否存在目标顺序的字符
-
#include
-
#include
-
#include
-
#include
-
#include
-
#define LL long long
-
using
namespace
std;
-
int main(){
-
int t;
-
char s[
101];
-
char ntes[
10]=
"NTES\0";
-
int len =
strlen(ntes);
-
cin>>t;
-
while(t--){
-
cin>>s;
-
int cnt =
0;
-
int l =
strlen(s);
-
for(
int i=
0;i
-
if(s[i]==ntes[cnt]){
-
cnt++;
-
}
-
if(cnt>len){
-
break;
-
}
-
}
-
//cout<
-
if(cnt == len){
-
cout<<
"yes"<<
endl;
-
}
-
else{
-
cout<<
"no"<<
endl;
-
}
-
}
-
return
0;
-
}
-
/*
-
2
-
STNETEDTS
-
TSENSTE
-
*/
第三题 树的深度
给出n 和 n行,n代表树有n个节点,接下来的n行,每一行有两个数字,代表该节点的左右子节点是否存在,1为存在,-1为不存在。节点输入的顺序有序,第一组为根节点的左右子节点,求树的最大深度。
分析:已知节点有序,证明同样深度的节点顺序出现,从子节点信息也可以累加下一层有多少个节点,因此只需要遍历输入,统计当前层和下一层有多少节点,累加深度即可
-
#include
-
#include
-
#include
-
#include
-
#include
-
#define LL long long
-
using
namespace
std;
-
struct node{
-
int left;
-
int right;
-
}tree[
101];
-
int main(){
-
int n;
-
cin>>n;
-
int father[
101];
-
int left,right;
-
int cp=
1;
-
int nextp=
0;
-
int dep =
1;
-
for(
int i=
0;i
-
cp--;
-
cin>>left>>right;
-
if(left>
0){
-
nextp+=
1;
-
}
-
if(right>
0){
-
nextp+=
1;
-
}
-
if(cp==
0){
-
cp=nextp;
-
if(cp>
0){
-
dep+=
1;
-
}
-
nextp=
0;
-
}
-
}
-
cout<
endl;
-
return
0;
-
}