算法 64式 7、搜索算法整理_第1部分_1到15题

1 算法思想

算法分类

搜索算法主要分为:

暴力搜索+剪枝,枚举,广度优先搜索,深度优先搜索,二分查找,哈希查找, A*算法,两边向中间逼近,从中间向两边扩散等

 

1.1枚举

枚举: 最直白的搜索方式,依次尝试搜索空间中的所有解。可以在搜索过程中通过加强条件约束来减少搜索范围图。

例如: 百鸡问题

 

1.2广度优先搜索(BFS)

含义:遍历解答树时使每次状态转移时扩展出尽可能多的状态,并按照各状态出现顺序依次扩展它们。

表现:在解答树上表现为树的层次遍历。

适用:可用于求解最优问题。因为其搜索到的状态总是按照某个关键字递增(例如时间,倒杯次数等)。一旦问题中出现最少,最短,最优等关键字,

       就需要考虑是否使用广度优先搜索。

实现: 一般用队列实现,用结构体保存每个状态,用标记数组防止无效搜索。

实现过程:

1)定义结构体用于保存每个状态,定义标记数组防止无效搜索

2)初始化第一个元素,并将该元素塞入队列中,设置第一个元素为已经访问

3)只要队列非空,得到并弹出队头元素,扩展得到新的元素,

对每个新元素,判断其如果满足约束条件并且是未遍历过的,

则更新新元素的状态,并将新元素塞入队列,设置新元素为已经访问过,

如果新元素是所求解,则直接返回

剪枝: 剪去解答树上不可能存在答案的子树。

 

1.3深度优先搜索(DFS)

含义: 优先遍历层次更深的状态,直到遇到一个状态节点不再拥有子树,则返回上一层,

访问其未被访问过的子树,直到解答树中所有状态被遍历完成。

适用: 深度优先搜索缺少广度优先搜索按层次递增顺序遍历的特性,深度优先搜索到的状态不再具有最优特性,深度优先搜索更多求解的是有解或者无解的问题。

实现: 通常使用递归实现。

实现过程:

1)扩展得到新元素,如果新元素不符合约束条件,则过滤该新元素;

2)基于当前状态更新得到新元素状态,判断新元素状态是否等于所求状态,如果是,设置结果标记为成功并直接返回;

3)否则,设置新元素为已经访问,递归处理,设置新元素为未访问(因为后续状态全部遍历完成,需要退回上层状态),如果结果标记为成功,则停止搜索

1.2 特点

1.3适用

1.4通用解法

广度优先搜索(BFS)算法:

1)定义结构体用于保存每个状态,定义标记数组防止无效搜索

2)初始化第一个元素,并将该元素塞入队列中,设置第一个元素为已经访问

3)只要队列非空,得到并弹出队头元素,扩展得到新的元素,

对每个新元素,判断其如果满足约束条件并且是未遍历过的,

则更新新元素的状态,并将新元素塞入队列,设置新元素为已经访问过,

如果新元素是所求解,则直接返回

 

 

深度优先搜索(DFS)算法:

1)扩展得到新元素,如果新元素不符合约束条件,则过滤该新元素;

2)基于当前状态更新得到新元素状态,判断新元素状态是否等于所求状态,如果是,设置结果标记为成功并直接返回;

3)否则,设置新元素为已经访问,递归处理,设置新元素为未访问(因为后续状态全部遍历完成,需要退回上层状态),如果结果标记为成功,则停止搜索

 

 

1.5经典例题讲解

广度优先搜索(BFS):

胜利大逃亡

我被魔王抓走,城堡是A*B*C的立方体,即A个B*C的矩阵,我被关在(0,0,0)位置,出口在(A-1,B-1,C-1),魔王在T分钟内回到城堡,

我每分钟能移动1个坐标。若走到出口恰遇魔王,也算成功。请输出多少分钟可以离开,不能则输出-1

代码:

typedef struct Stat                //定义结构体用于保存每个状态

{

       int x,y,z;//坐标

       int t;//从(0,0,0)到达该坐标的时间

}Stat;//保存当前节点的状态

 

int maze[N][N][N];//用于标识每一个坐标是0:路,1:墙

bool mark[N][N][N];// 定义标记数组防止无效搜索,用于标识该坐标是否已经搜索过,false:未搜索过,true:搜索过,便于剪枝

int goNext[][3] =

{1,0,0,

-1,0,0,

0,1,0,

0,-1,0,

0,0,1,

0,0,-1};//用于进行下一次6个可达状态的遍历

 

queue queueStat;

 

//进行深度遍历,无需判断超时

int BFS(int a,int b,int c)

{

       //只要队列不空,说明仍有状态需要遍历

       while(!queueStat.empty())

       {

              //弹出当前状态,进行状态迁移

              Stat stat = queueStat.front();

              queueStat.pop();

 

              //遍历6种状态,扩展得到新的元素

              int x,y,z;

              for(int i = 0 ; i < 6 ; i++)

              {

                     x = stat.x + goNext[i][0];

                     y = stat.y + goNext[i][1];

                     z = stat.z + goNext[i][2];

 

                     //对每个新元素,判断其如果满足约束条件并且是未遍历过

// 判断是否仍在围墙中

                     //易错,这里城堡的位置是不能为a,因为这是数组,这样做就超过了

                     //if(x < 0 || x > a || y < 0 || y > b || z < 0 || z > c)

                     if(x <0 || x >= a || y < 0 || y >=b || z < 0 || z >= c )

                     {

                            continue;

                     }

 

                     //如果已经遍历过,则跳过

                     if(true==mark[x][y][z])

                     {

                            continue;

                     }

                     //如果下一个是墙,则跳过

                     if(1==maze[x][y][z])

                     {

                            continue;

                     }

 

                     //更新新元素的状态,并将新元素塞入队列,设置新元素为已经访问过

                     Stat statTemp;

                     statTemp.x = x;

                     statTemp.y = y;

                     statTemp.z = z;

                     statTemp.t = stat.t + 1;//所耗时间进行累加

 

                     //易错,更新剪枝状态

                     mark[x][y][z] = true;

 

                     //将新状态放入队列

                     queueStat.push(statTemp);

 

           //如果新元素是所求解,则直接返回

                     //判断是否已经到达终点,则返回其所耗时间

                     if(a-1==x && b-1==y && c-1==z)

                     {

                            return statTemp.t;

                     }

              }//for

       }//while

       return -1;//如果一直没有找到,返回-1

}

 

 

深度优先搜索(DFS)

Temple of the bone

有一个N*M的迷宫,起点S,终点D,墙X和地面,'.'表示路,0秒时,我从S出发,

每秒能走到4个与其相邻位置的任意一个,行走之后不能再次走入。

问:是否存在一条路径使主人公刚好在T秒走到D

代码

typedef struct Stat

{

       int x,y;//横纵坐标

       int t;//耗费时间

}Stat;

 

char maze[N][N];//保存迷宫元素

bool success;//设置是否找到的成功标记

 

//走下一个位置的数组

int goNext[][2] =

{0,1,

-1,0,

1,0,

0,-1

};

 

//深度优先搜索

void DFS(int x,int y,int t,int n,int m,int tLimit)

{

       int i ;

    // 扩展得到新元素

       for(i = 0 ; i < 4 ; i ++)

       {

              int iXNext = x + goNext[i][0];

              int iYNext = y + goNext[i][1];

 

        // 如果新元素不符合约束条件,则过滤该新元素

              //判定有无超过迷宫位置

              if(iXNext < 1 || iXNext > n || iYNext < 1 || iYNext > m)

              {

                     continue;

              }

              //判定是否是墙

              if('X'==maze[iXNext][iYNext])

              {

                     continue;

              }

        // 基于当前状态更新得到新元素状态,判断新元素状态是否等于所求状态,如果是,设置结果标记为成功并直接返回

              //判定是否到达终点,并且时间要符合

              if('D'==maze[iXNext][iYNext] && tLimit==(t + 1))

              {

                     //易错,需要设置成功标记

                     success = true;

                     return;

              }

       

        //设置新元素为已经访问,递归处理,设置新元素为未访问(因为后续状态全部遍历完成,需要退回上层状态),如果结果标记为成功,则停止搜索

              maze[iXNext][iYNext] = 'X';

              //递归调用

              DFS(iXNext,iYNext,t+1,n,m,tLimit);

              //若其后续状态全部遍历完毕,返回上层状态,因为要搜索后续状态,因此再将墙改为普通状态

              maze[iXNext][iYNext] = '.';

 

              //易错,判断是否搜索成功

              if(true==success)

              {

                     return;

              }

       }//for

       //如果一直遍历不到,则返回-1

       return;

}

 

 

2 搜索系列

类别-编号

题目

遁去的1

1

找x

输入一个数n,输入n个数值不同的数,输入给定值x,输出x在数组中的下标,从0开始,若不在数组中则输出-1

 

输入:

2

1 3

0

输出:

-1

计算机考研—机试指南

https://blog.csdn.net/qingyuanluofeng/article/details/97750108

思路:用哨兵,从后向前搜索

代码:

 

int main(int argc,char* argv[])

{

       int iNum;

       while(EOF!=scanf("%d",&iNum) && iNum >= 1 && iNum <= 200)

       {

              //bool isBreak = false;

              int* iArr = (int*)malloc(iNum*sizeof(iNum));

              int iValue;

              for(int i = 0;i < iNum ; i++)

              {

                     scanf("%d",&iValue);

                     *(iArr+i) = iValue;

              }

              int iSearch;

              scanf("%d",&iSearch);

              int iSoladir = -1;//设置哨兵

              for(int j = iNum-1 ; j > iSoladir ; j--)

              {

                     if(iArr[j]==iSearch)

                     {

                            printf("%d",j);

                            //isBreak = true;

                            break;

                     }

              }

              if(j==iSoladir)

              {

                     printf("%d",j);

              }

              free(iArr);

       }

       getchar();

       return 0;

}

2

统计同成绩学生人数

读入N名学生的成绩,将获得某一给定分数的学生人数输出

 

输入

3

80 60 90

60

2

85 66

0

5

60 75 90 55 75

75

0

输出:

1

0

2

计算机考研—机试指南

https://blog.csdn.net/qingyuanluofeng/article/details/47159633

思路:

在给定的数中,找到最大的数,找到小于该最大数的最大质数,然后用每个数去除以该质数,得到的值就存放在A[1000]中相应的下标位置

在给定一个分数,计算出哈希值,

 

哈希的思路:

Hash[x] 保存的是数字x出现的次数,建立了一种一一映射的关系

 

关键:

1 Hash[x] 保存的是数字x出现的次数,建立了一种一一映射的关系

2 判断输入的数字是不是0,不要放在循环体内,只需要放到循环条件内

  while(EOF!=scanf("%d",&n) && n!=0)

 

代码:

int main(int argc,char* argv[])

{

       int iNum;

       bool isExit = false;

       int iBuf[20][1000];

       int iGiv[20];

       int iRes[20];

       int k = 0;

       while(EOF!=scanf("%d",&iNum))

       {

              if(0 > iNum || iNum > 1000)

              {

                     break;

              }

              else if(0==iNum)

              {

                     //isExit = true;

                     break;

              }

              int iValue,i;

              for(i = 0; i < iNum ; i++)

              {

                     scanf("%d ",&iValue);

                     if(iValue < 0 || iValue > 100)

                     {

                            break;

                     }

                     else

                     {

                            iBuf[k][i] = iValue;

                     }

              }

              int iGivSco;

              scanf("%d",&iGivSco);

              iGiv[k] = iGivSco;

              int count = 0;

              for(i = 0; i < iNum ;i++)

              {

                     if(iBuf[k][i]==iGivSco)

                     {

                            count++;

                     }

              }

              iRes[k] = count;

              k++;

       }

       //这边k不需要减1,因为k是用来做数组循环的

       for(int j = 0; j < k; j++)

       {

              printf("%d\n",iRes[j]);

       }

       system("pause");

       getchar();

       return 0;

}

3

百鸡问题

:<=n元买100只鸡,大鸡5元每只,小鸡3元每只,还有1/3元每只的小鸡,分别记为x只,y只,z只,求所有解

 

输入:输入n

输出:对于每组输入,输出x y z ,按照x,y,z依次增大顺序输出

输入:

40

输出:

x=0,y=0,z=100

x=0,y=1,z=99

x=0,y=2,z=98

x=1,y=0,z=99

计算机考研—机试指南

https://blog.csdn.net/qingyuanluofeng/article/details/47186199

易错:n元不需要全部用掉,必须用浮点数,因为有1/3

思路:枚举x,y,而z=100-x-y

 

代码:

int main(int argc,char* argv[])

{

       int n;

       int x,y;

       while(EOF!=scanf("%d",&n) || n>0)

       {

              for(x = 0; x <= 20 ; x ++)

              {

                     for(y = 0 ; y <= 33 ; y++)

                     {

                            if( (5*x+3*y+1.0*(100-x-y)/3) <= n )

                            {

                                   printf("x=%d,y=%d,z=%d\n",x,y,100-x-y);

                            }

                     }

              }

       }

       system("pause");

       getchar();

       return 0;

}

4

胜利大逃亡

我被魔王抓走,城堡是A*B*C的立方体,即A个B*C的矩阵,我被关在(0,0,0)位置,出口在(A-1,B-1,C-1),魔王在T分钟内回到城堡,我每分钟能移动1个坐标。若走到出口恰遇魔王,也算成功。请输出多少分钟可以离开,不能则输出-1

计算机考研—机试指南

https://blog.csdn.net/qingyuanluofeng/article/details/47186231

 

参见经典例题解析

5

非常可乐

要用N,M,S三个杯子均匀分出2杯可乐,S=N+M,00,M>0。如果能够平分,请输出倒出可乐的最少次数,如果不能输出"NO"

输入:3个整数,S 可乐的体积,N和M是两个杯子的容量,以"0 0 0"结束

输出:若可以平分,输出最少要倒的次数,否则输出NO

 

输入:3个整数,S 可乐的体积,N和M是两个杯子的容量,以"0 0 0"结束

输出:若可以平分,输出最少要倒的次数,否则输出NO

输入:

7 4 3

4 1 3

0 0 0

输出:

NO

3

计算机考研—机试指南

https://blog.csdn.net/qingyuanluofeng/article/details/47186245

思路:用四元组(x,y,z,t)表示一个状态,x,y,z表示3个瓶子中的体积,t表示从初始状态到该平分状态需要倾倒的次数的状态之间的相互扩展。平分状态第一次被搜索出的次数

     即为所求。若t不是最少次数,则状态为无效状态,将其舍弃。

关键:

1 需要一个倾倒函数,来标记两个杯子之间的状态

2 平分的时候只要3个杯子中任意2个杯子各的总体积的一半就可以

3 3个杯子两两相互倾倒共有6次,而且需要注意方向,a倒向b与b倒向a是不同的

4 初始化将s,n,m之间的剪枝状态置为false,注意每次使用之前清空队列,每次设定起始节点,并设置剪枝状态

5 int puts(char* str),将字符串写到标准输出上,成功返回非负值,失败返回EOF

6 注意更新后的状态必须要用更新后的东西,初始体积必须为偶数,否则不能平分。注意iVa -= (iConB - iVb)必须先求,放在后面值都改变了

 

代码:

typedef struct Stat

{

       int x,y,z;//三个瓶子的体积

       int t;//从初始状态到平分状态的倾倒次数

}Stat;

 

bool mark[N][N][N];//剪枝状态

int maze[N][N][N];//

 

queue queueStat;//保存状态的队列

 

//倾倒函数,iConA是容器A的体积,iVa是容器A中的原来的体积。将容器A中体积倒往容器B中,注意要用引用

void Dump(int iConA,int& iVa,int iConB,int& iVb)

{

       //注意,由于容器没有刻度,要么将一个容器中的所有可乐全倒,或者将另一个容器加满

       //如果B容器能够容纳A容器中所有可乐,则全部倒出

       if(iConB >= iVa + iVb)

       {

              iVb += iVa;

              iVa = 0;

       }

       else

       {

              iVa -= (iConB - iVb);

              iVb = iConB;

              //iVa = iVa - (iConB - iVb);//这里错了,应该先计算iVa的值,因为iVb与iConB的值一样了,所以没有发生改变

       }

}

 

int BFS(int s,int n,int m)

{

       int x,y,z;

       while(!queueStat.empty())

       {

              Stat stat = queueStat.front();

              queueStat.pop();

              x = stat.x;

              y = stat.y;

              z = stat.z;

 

              //从S倒向N

              Dump(s,x,n,y);

              if(mark[x][y][z]==false)

              {

                     //进行剪枝

                     mark[x][y][z] = true;

                     //生成新状态

                     Stat statNew;

                     statNew.x = x;

                     statNew.y = y;

                     statNew.z = z;

                     statNew.t = stat.t + 1;

                     //判断是否达到平分状态

                     if( (x==s/2 && y==s/2) || (x==s/2 && z==s/2) || (y==s/2 && z==s/2))

                     {

                            return statNew.t;

                     }

                     //没有达到平分状态,则放入队列中

                     queueStat.push(statNew);

              }

 

              //重置初始状态,并进行状态更新

              x = stat.x;

              y = stat.y;

              z = stat.z;

              //从N倒向S

              Dump(n,y,s,x);

              if(mark[x][y][z]==false)

              {

                     //进行剪枝

                     mark[x][y][z] = true;

                     //生成新状态

                     Stat statNew;

                     statNew.x = x;

                     statNew.y = y;

                     statNew.z = z;

                     statNew.t = stat.t + 1;

                     //判断是否达到平分状态

                     if( (x==s/2 && y==s/2) || (x==s/2 && z==s/2) || (y==s/2 && z==s/2))

                     {

                            return statNew.t;

                     }

                     //没有达到平分状态,则放入队列中

                     queueStat.push(statNew);

              }

 

              //重置初始状态,并进行状态更新

              x = stat.x;

              y = stat.y;

              z = stat.z;

              //从S倒向M

              Dump(s,x,m,z);

              if(mark[x][y][z]==false)

              {

                     //进行剪枝

                     mark[x][y][z] = true;

                     //生成新状态

                     Stat statNew;

                     statNew.x = x;

                     statNew.y = y;

                     statNew.z = z;

                     statNew.t = stat.t + 1;

                     //判断是否达到平分状态

                     if( (x==s/2 && y==s/2) || (x==s/2 && z==s/2) || (y==s/2 && z==s/2))

                     {

                            return statNew.t;

                     }

                     //没有达到平分状态,则放入队列中

                     queueStat.push(statNew);

              }

 

              //重置初始状态,并进行状态更新

              x = stat.x;

              y = stat.y;

              z = stat.z;

              //从M倒向S

              Dump(m,z,s,x);

              if(mark[x][y][z]==false)

              {

                     //进行剪枝

                     mark[x][y][z] = true;

                     //生成新状态

                     Stat statNew;

                     statNew.x = x;

                     statNew.y = y;

                     statNew.z = z;

                     statNew.t = stat.t + 1;

                     //判断是否达到平分状态

                     if( (x==s/2 && y==s/2) || (x==s/2 && z==s/2) || (y==s/2 && z==s/2))

                     {

                            return statNew.t;

                     }

                     //没有达到平分状态,则放入队列中

                     queueStat.push(statNew);

              }

 

              //重置初始状态,并进行状态更新

              x = stat.x;

              y = stat.y;

              z = stat.z;

              //从N倒向M

              Dump(n,y,m,z);

              if(mark[x][y][z]==false)

              {

                     //进行剪枝

                     mark[x][y][z] = true;

                     //生成新状态

                     Stat statNew;

                     statNew.x = x;

                     statNew.y = y;

                     statNew.z = z;

                     statNew.t = stat.t + 1;

                     //判断是否达到平分状态

                     if( (x==s/2 && y==s/2) || (x==s/2 && z==s/2) || (y==s/2 && z==s/2))

                     {

                            return statNew.t;

                     }

                     //没有达到平分状态,则放入队列中

                     queueStat.push(statNew);

              }

 

              //重置初始状态,并进行状态更新

              x = stat.x;

              y = stat.y;

              z = stat.z;

              //从M倒向N

              Dump(m,z,n,y);

              if(mark[x][y][z]==false)

              {

                     //进行剪枝

                     mark[x][y][z] = true;

                     //生成新状态

                     Stat statNew;

                     statNew.x = x;

                     statNew.y = y;

                     statNew.z = z;

                     statNew.t = stat.t + 1;

                     //判断是否达到平分状态

                     if( (x==s/2 && y==s/2) || (x==s/2 && z==s/2) || (y==s/2 && z==s/2))

                     {

                            return statNew.t;

                     }

                     //没有达到平分状态,则放入队列中

                     queueStat.push(statNew);

              }

       }

       //如果都没有找到,直接返回-1

       return -1;

}

6

Temple of the bone

有一个N*M的迷宫,起点S,终点D,墙X和地面,'.'表示路,0秒时,我从S出发,每秒能走到4个与其相邻位置的任意一个,行走之后不能再次走入。问:是否存在一条路径使主人公刚好在T秒走到D

计算机考研—机试指南

https://blog.csdn.net/qingyuanluofeng/article/details/47186307

 

参见经典例题解析

7

Oil Deposit

在n*m的图中,确定有几个@块,块符合以下条件:其中任意对@块均直接或间接相通,两个@直接相邻或者对角相邻即被视为连通

输入:m(行号) n(列号),m=0标志输入结束,1<=m,n<=100,接下来是m行每行中有n个字符。每个字符对应一块土地,*代表没有石油,@代表有石油

输出:对于每个格子,输出有多少个石油存储区。2个不同的石油处垂直,水平,对角线属于同一个石油存储区。石油存储区<=100

计算机考研—机试指南

https://blog.csdn.net/qingyuanluofeng/article/details/47186293

思路:对图上所有位置设置标记位,该标记仅对@有效,按从左到右,从上到下顺序遍历地图上所有位置,如果遍历到@,且未被标记,

则所有与其直接相邻或间接相邻的@点与其一起组成一个块,将该块中所有的@位置标记为已经计算。

关键:

1 按行输入,maze[i] + 1,scanf("%s",maze[i]+1);//不能加上\n,且maze[i]后面需要加上1

2 凡是用栈均是深度优先

3 薄弱:二维指针

4 在设置剪枝标记时与递归过程分开,在递归的主调函数中要进行过滤,每递归结束1次,进行一次累加

 

代码:

#define N 101

bool mark[N][N];//剪枝标记

char maze[N][N];//迷宫坐标,存储元素

int goNext[][2] =

{-1,1,

0,1,

1,1,

-1,0,

1,0,

-1,-1,

0,-1,

1,-1

};//8个位置的下一个走法

 

//n:行号,m:列号,x:横坐标,y:纵坐标

void DFS(int x,int y,int n,int m)

{

       //判定8个位置的下一个走法

       int iXNext,iYNext;

       for(int i = 0; i < 8 ; i++)

       {

              iXNext = x + goNext[i][0];

              iYNext = y + goNext[i][1];

 

              //如果已经标记或者超出范围或者为*均跳过

              if(true==mark[iXNext][iYNext] || '*'==maze[iXNext][iYNext] || (iXNext < 0 || iXNext > n || iYNext < 0 || iYNext >m))

              {

                     continue;

              }

              else

              {

                     //如果没有则递归调用,调用之前先设置标记为真

                     mark[iXNext][iYNext] = true;

                     DFS(iXNext,iYNext,n,m);

              }

       }

}

 

int main(int argc,char* argv[])

{

       int n,m;

       int i,j;

       while(EOF!=scanf("%d %d",&n,&m))

       {

              if(n < 1 || n > 100 || m < 1 || m > 100)

              {

                     break;

              }

 

              //接受输入信息

              for(i = 1 ; i <=n ; i++)

              {

                     //按行输入?

                     scanf("%s",maze[i]+1);//不能加上\n

              }

 

              //初始化剪枝标记

              for(i = 1 ; i <= n ; i++)

              {

                     for(j = 1 ; j <= m ; j++)

                     {

                            mark[i][j] = false;

                     }

              }

 

              //开始进行递归遍历,设置限定条件

              int iCnt = 0;//设定石油存储区计数器初始化为0

              for(i = 1 ; i <= n ; i++)

              {

                     for(j = 1; j <= m ; j++)

                     {

                            if(true==mark[i][j] || '*'==maze[i][j])

                            {

                                   continue;

                            }

                            else

                            {

                                   DFS(i,j,n,m);

                                   iCnt++;

                            }

                     }

              }

              printf("%d\n",iCnt);

       }

       system("pause");

       getchar();

       return 0;

}

8

构造数独
数独的棋盘是由九九八十一个小方格组成的。玩家在每个小格子中,分别天上1至9的任意一个数字,让整个棋盘每一行,每一列,以及每一个3*3的小矩阵中的数字都不重复。

编程之美

https://blog.csdn.net/qingyuanluofeng/article/details/39273281

使用一个二维数组来存储,每一个元素对应数独中的一个数。但考虑到每一个格子有若干属性,可以把每个格子抽象为一个对象,把整体看成9*9个格子对象

生成游戏初始局面:可以向生成一个完整合法的解,然后再随机地去掉一些数字。

 

解法1:

假设用下面的结构来存储数独游戏:

int _size = 9;

Cell[,] _cells;

下面的GenerateValidMatrix()函数用经典的深度优先搜索来生成一个可行解。从(0,0)开始,对没有处理过的格子,调用GetValidValueList(coCurrent)来获得当前

格子可能的取值选择,并从中取一个为当前格子的取值,接着搜索下一个格子。在搜索uocheng中,若出现某个格子没有可行的值,则回溯,修改前一个格子的取值。

直到所有的格子都找到可行的取值为止,这是可行解。

 

没有完成

9

只考加法的面试题:

1+2=3

4+5=9

2+3+4=9

写一个程序,对于64位正整数,输出它所有可能的连续自然数(两个以上)之和的形式

 

输入:

9

21

10

输出:

4+5=9

2+3+4=9

10+11=21

6+7+8=21

1+2+3+4+5+6=21

1+2+3+4=10

编程之美

https://blog.csdn.net/qingyuanluofeng/article/details/47187499

思路:

可以采用暴力求解。以上限n/2+1 + n/2作为起始点,如果满足,输出;不满足时肯定是偏大,那么使n/2向左移动,再次计算,如果仍然偏大,就向左移动n/2+1;

偏小向左移动左边指针,偏大向左移动右边指针,如果当左边移动到1处循环截止

 

void successiveNumAdd(long long n)

{

       static int iCnt = 0;

       if(n <= 0)

       {

              return;

       }

       long long iLow = n/2;

       long long iHigh = n/2+1;

       if((n & 1) == 0)//如果是偶数,就将iLow与iHigh都减1

       {

              iLow--;

              iHigh--;

       }

       int iSum;

       while(iLow > 0)//iLow == 0时,表示循环结束

       {

              iSum = ((iLow + iHigh)*(iHigh - iLow + 1))/2;//;利用等差公式求和

              if(iSum > n )//如果所求的和大于原来的数,让iHigh--(这样会减小)

              {

                     iHigh--;

              }

              else if(iSum < n)//如果所求的和小于原来的数,让iLow--(这样会增大)

              {

                     iLow--;

              }

              else//我们知道一旦等于以后,后面应该让iHigh--,使其减小,然后后面通过iLow--再使数增大起来

              {

                     for(int i = iLow ; i <= iHigh ; i++)

                     {

                            if(i != iLow)

                            {

                                   printf("+%d",i);

                            }

                            else

                            {

                                   printf("%d",i);

                            }

                     }

                     printf("=%d\n",n);

                     iHigh--;

                     iCnt++;

              }

       }

       printf("%d\n",iCnt);

}

10

数字哑谜和回文

1神奇的9位数。能不能找出符合如下条件的9位数:

这个数包括了1~9这9个数字;

这个9位数的前n位都能被n整除,若这个数表示为abcdefghi,则ab可以被2整除,abc可以被3整除......abcdefghi可以被9整除

 

输入:

输出:

381654729

编程之美

https://blog.csdn.net/qingyuanluofeng/article/details/47187997

分析:

问题1的解法1:

假设这个9位数是abcdefghi,,诶个字符对应1~9之间的数。可以考虑剪枝来优化性能。

剪枝=避开死胡同,把搜索比作遍历一棵树,那么剪枝就是讲数中的一些不能到达的枝条剪掉。

比如循环到b等于奇数时,ab必须被2整除,b必须为偶数。

问题1的解法2:

试一试用逻辑推理的办法来求解这个问题,假设每个字符目前都可以对应1~9之间的任何数字。

a    1 2 3 4 5 6 7 8 9

b    1 2 3 4 5 6 7 8 9

c    1 2 3 4 5 6 7 8 9

d    1 2 3 4 5 6 7 8 9

e    1 2 3 4 5 6 7 8 9

f    1 2 3 4 5 6 7 8 9

g    1 2 3 4 5 6 7 8 9

h    1 2 3 4 5 6 7 8 9

i    1 2 3 4 5 6 7 8 9

把整除的条件列出来,

a被1整除,任何数都满足这个条件,

b为0,2,4,6,8

abc必须被3整除,那么a+b+c=3*k

abcd必须被4整除,那么d必须为2,4,6,8,cd被4整除

abcde被5整除,e为5(0为什么不可能,因为是1~9,没有0)

abcdef被6整除,f = 2,4,6,8,a+b+c+d+e+f=3*k,不易想到

abcdefg被7整除,abcd -efg能被7整除(考虑到7能整除1001),不易想到

abcdefgh被8整除,h = 2,4,6,8,fgh能被8整除,不易想到

abcdefghi被9整除,a+b+c+d+e+f+g+h+i=9*k,不易想到

范围如下:

a 1 3 7 9

b 2 4 6 8

c 1 3 7 9

d 2 4 6 8

e 5

f 2 4 6 8

g 1 3 7 9

h 2 4 6 8

i 1 3 7 9

下面条件:

a+b+c被3整除

cd被4整除

d+e+f被3整除

abcd-efg能被7整除

fgh能被8整除

因为d +e +f被3整除,而e = 5,则d + f = 3k + 1形式

{d=2   {d=4  {d=6  {d=8

{f=8   {f=6  {f=4  {f=2

由于cd被4整除,cd=12,16,32,36,72,76,92,96

d=2或6

f=8或4

fgh被8整除

fgh=816,832,872,896,416,432,472,496

f=8时,d=2,故h不能为2

f=4时, d=6,故h不能为6

fgh=816,896,432,472

简化结果:

a 1 3 7 9

b 4 8

c 1 3 7 9

d 2 6

e 5

f 8 4

g 1 3 7 9

h 6 2

i 1 3 7 9

未使用的条件有:

a+b+c被3整除,abcd-efg能被7整除(考虑到7能整除1001)

cd  = 12,16,32,36,72,76,92,96

df = 28,64

 

bool isDifferent(int a,int b,int c,int d,int e,int f,int g,int h,int i)

{

       int iMark[10];

       memset(iMark,0,sizeof(iMark));

       iMark[a]++;

       iMark[b]++;

       iMark[c]++;

       iMark[d]++;

       iMark[e]++;

       iMark[f]++;

       iMark[g]++;

       iMark[h]++;

       iMark[i]++;

       for(int i = 1 ; i <= 9 ; i++)

       {

              if(iMark[i] != 1)

              {

                     return false;

              }

       }

       return true;

}

 

long nineBitNum_pruning()//pruning剪枝,限制条件更多

{

       int e = 5;s

       for(int a = 1 ; a <= 9 ; a += 2)

       {

              if(5 == a)

              {

                     continue;

              }

              for(int b = 4 ; b <= 8 ; b += 4)

              {

                     for(int c = 1; c <= 9 ; c += 2)

                     {

                            if(5 == c)

                            {

                                   continue;

                            }

                            for(int d = 2 ; d <= 6 ; d += 4)

                            {

                                   for(int f = 4 ; f <= 8 ; f += 4)

                                   {

                                          for(int g = 1 ; g <= 9 ; g += 2)

                                          {

                                                 if(5 == g)

                                                 {

                                                        continue;

                                                 }

                                                 for(int h = 2 ; h <= 6; h += 4)

                                                 {

                                                        for(int i = 1 ; i <= 9 ; i += 2)

                                                        {

                                                               if(i == 5)

                                                               {

                                                                      continue;

                                                               }

                                                               if((a + b + c) % 3 == 0 && (1000*a + 100*b + 10*c + d - 100*e - 10*f -g) % 7 == 0

                                                                      && isDifferent(a,b,c,d,e,f,g,h,i))

                                                               {

                                                                      return (long)(a*1e8 + b*1e7 + c*1e6 + d*1e5 + e*1e4 + f*1e3 + g*1e2 + h*1e1 + i);

                                                               }

                                                        }

                                                 }

                                          }

                                   }

                            }

                     }

              }

       }

       return -1;

}

 

 

int isValid(int a,int b,int c,int d,int e,int f,int g,int h,int i)

{

       if((a + b + c) % 3 == 0 && (1000*a + 100*b + 10*c + d - 100*e - 10*f -g) % 7 == 0

                                                                      && isDifferent(a,b,c,d,e,f,g,h,i))

                                                               {

                                                                      return (long)(a*1e8 + b*1e7 + c*1e6 + d*1e5 + e*1e4 + f*1e3 + g*1e2 + h*1e1 + i);

                                                               }

       return -1;

}

11

数字哑谜和回文2

有这样一个乘法算式:

人过大佛寺*我=寺佛大过人

这里面每一个字都代表着一个数字,并且不同的字代表的数字不同,你能把这些数字都找出来吗?

 

输出:

21978*4=87912

编程之美

https://blog.csdn.net/qingyuanluofeng/article/details/47188021

代码:

bool isDifferent(int* pArr,int iLen)

{

       int iMark[10] = {0};

       for(int i = 0 ; i < iLen ; i++)

       {

              iMark[ pArr[i] ]++;

       }

       int iCnt = 0;

       for(int i = 0 ; i <= 10; i++)

       {

              if(iMark[i] == 1)

              {

                     iCnt++;

              }

       }

       if(iCnt != iLen)

       {

              return false;

       }

       else

       {

              return true;

       }

}

 

void process()

{

       int iTemp,iCnt,iProduct;

       int iArr[10];

       for(int i = 12345 ; i <= 99999/2 ; i++)//从低向高,检测

       {

              iTemp = i;

              iCnt = 0;

              do{//将5位数进行拆分,从个位拆分到最高位

                     iArr[iCnt++] = iTemp % 10;

                     iTemp /= 10;

              }while(iTemp);

             

              for(int j = 2 ; j <= 9; j++)//如果6个数不同

              {

                     iArr[iCnt] = j;

                     if(isDifferent(iArr,iCnt+1))

                     {

                            iProduct = i * j;

                            if(iProduct == (1e4*iArr[0] + 1e3*iArr[1] + 1e2*iArr[2] + 1e1*iArr[3] + iArr[4]))//检验是否相等

                            {

                                   printf("%d*%d=%d\n",i,j,iProduct);

                            }

                     }

              }

       }

}

12

判断字符串所有字符全都不同

实现算法,确定字符串所有字符是否全都不同

 

输入:

chaoyan

zhuwenpi

输出:

repeated

different

程序员面试金典

https://blog.csdn.net/qingyuanluofeng/article/details/53759385

关键:

1 大于256个字符,必定重复

2 设定一个布尔数组,初始化该数组每个元素为否,表明没有

重复出现,如果某字符首次出现,则设定为true,如果某字符对应已经为true,说明重复

3 考虑如果字母仅为'a'到'z',则一个int包含32位,则可以采用“&”的方式做,减去‘a’

  相与后大于0,说明重复

 

代码:

bool isRepeated(string str)

{

       //为空必定不重复

       if(str.empty())

       {

              return false;

       }

       int length = str.size();

       if(length > 256)

       {

              return true;

       }

       int flags[MAXSIZE];

       memset(flags , 0 , sizeof(flags) );

       for(int i = 0; i < length ; i++)

       {

              int ch = str[i];

              //如果之前已经出现过了,那么说明重复

              if( 1 == flags[ch] )

              {

                     return true;

              }

              //之前没有出现过

              else if(0 == flags[ch])

              {

                     flags[ch] = 1;

              }

       }

 

       //如果之前一直都没有重复,走到这里说明也没有重复

       return false;

}

 

//假设只有'a'~'z' 26个字母,而一个int包含32位,则可以采用“&”的方式做

bool isRepeated_aToZ(string str)

{

       //为空必定不重复

       if(str.empty())

       {

              return false;

       }

       int length = str.size();

       if(length > 256)

       {

              return true;

       }

       int checker = 0;

       for(int i = 0 ; i < length ; i++)

       {

              //注意要减去字符

              int ch = str[i] - 'a';

              int res = checker & (1 << ch);

 

              //说明该字母已经出现过,这里不是1,应该是大于0,因为不一定在1上

              if(res > 0)

              {

                     return true;

              }

              checker |= (1 << ch);

       }

       return false;

}

13

魔术索引

在数组A[0 ... n-1]中,有所谓的魔术索引,满足条件A[i] = i。给定一个

有序整数数组,元素值各不相同,编写一个方法,在数组A中找出一个魔术索引,如果存在的话。

 

输入:

7(元素个数)

-3 -1 2 3 4 7 8

7

1 2 3 4 5 6 7

输出:

3

-1

程序员面试金典

https://blog.csdn.net/qingyuanluofeng/article/details/54234581

 

分析: 因为A{i] = i,所以魔术索引对应 A[i] - i = 0,

      可以猜想,将令数组A中A[i] = A[i] - i 得到的应该是类似如下这种

         ...-2 -1 0 0 0 1 2....

         问题转换成了为:二分查找,而且是二分查找中查找lowwer和upper的算法

二分查找之lowwer_bound:这个是找到大于等于某元素首次出现的位置

          upper_bound:找到大于元素第一次出现的位置

求下边界算法:设low,high表示数组A下标和上标

中间值<查找值,说明查找值在中间值的右侧,令下标low=middle+1,在[middle+1,high]中继续查找

中间值>查找值,中间值可能是解,找值在中间值及其左侧,令上标high = middle;

中间值=查找值,由于是要找到大于或等于某元素首次出现位置,那么当前值是有有可能的查找值应该在下标到当前中间值中继续查找,high=middle;

合并之后:

中间值<查找值,low = middle+1

中间值>=查找值,high=middle

何时终止? 主要是判断low high,终止;low = high时,如果A[low] = 待查找值,直接返回

           low,否则返回-1

求上边界算法:

中间值<查找值,说明查找值在中间值右侧,令下标low=middle+1,在[middle+1,high]中继续查找

中间值>查找值,中间值可能是解,查找值在中间值及其左侧,令上标high = middle ;

中间值=查找值,中间值不可能是解,那么查找值应该在下标到当前中间值中继续查找,low=middle+1;

合并:

中间值<=查找值,low=middle+1

中间值>查找值,high = middle;

 

关键:

1 二分查找之lowwer_bound:这个是找到大于等于某元素首次出现的位置

          upper_bound:找到大于元素第一次出现的位置

求下边界算法:设low,high表示数组A下标和上标

中间值<查找值,说明查找值在中间值的右侧,令下标low=middle+1,在[middle+1,high]中继续查找

中间值>查找值,中间值可能是解,找值在中间值及其左侧,令上标high = middle;

中间值=查找值,由于是要找到大于或等于某元素首次出现位置,那么当前值是有有可能的查找值应该在下标到当前中间值中继续查找,high=middle;

//二分查找值,寻找某个元素首次出现的下标

int lowwer_bound(int* pArray , int low , int high , int value)

{

       if(NULL == pArray || low > high || low < 0 || high < 0)

       {

              return -1;

       }

       int middle;

       while( low <= high ) // "="取的原因是,同一个区间需要去做最后一次判定,否则遗漏一次判定操作

       {

         middle = low + (high - low)/2;

         if(pArray[middle] < value )

         {

                low = middle + 1;

         }

         //但注意会陷入死循环,存在low=high,则A[low]=A[high] ,p[m] >= value的情况,这种说明已经找到了

         else

         {

                if( low == high )

                {

                       //找到结果,直接返回

                       if( pArray[low] >= value)

                       {

                              return low;

                       }

                       else

                       {

                              return -1;

                       }

                }

                high = middle;

         }

       }

       //如果走到这里,就认为查找不到

       return -1;

}

2 求上边界算法:

中间值<查找值,说明查找值在中间值右侧,令下标low=middle+1,在[middle+1,high]中继续查找

中间值>查找值,中间值可能是解,查找值在中间值及其左侧,令上标high = middle ;

中间值=查找值,中间值不可能是解,那么查找值应该在下标到当前中间值中继续查找,low=middle+1;

 

 

代码:

 

int upper_bound(int* pArray , int low , int high , int value)

{

       if(NULL == pArray || low > high || low < 0 || high < 0)

       {

              return -1;

       }

       int middle;

       while( low <= high )

       {

              middle = low + (high - low)/2;

              if(pArray[middle] <= value)

              {

                     low = middle + 1;

              }

              else

              {

                     if(low == high)

                     {

                       //找到结果,直接返回

                       if( pArray[low] > value)

                       {

                              return low;

                       }

                       else

                       {

                              return -1;

                       }

                     }

                     high = middle;

              }

       }

       return -1;

}

 

//二分查找值,寻找某个元素首次出现的下标

int lowwer_bound(int* pArray , int low , int high , int value)

{

       if(NULL == pArray || low > high || low < 0 || high < 0)

       {

              return -1;

       }

       int middle;

       while( low <= high ) // "="取的原因是,同一个区间需要去做最后一次判定,否则遗漏一次判定操作

       {

         middle = low + (high - low)/2;

         if(pArray[middle] < value )

         {

                low = middle + 1;

         }

         //但注意会陷入死循环,存在low=high,则A[low]=A[high] ,p[m] >= value的情况,这种说明已经找到了

         else

         {

                if( low == high )

                {

                       //找到结果,直接返回

                       if( pArray[low] >= value)

                       {

                              return low;

                       }

                       else

                       {

                              return -1;

                       }

                }

                high = middle;

         }

       }

       //如果走到这里,就认为查找不到

       return -1;

}

 

//二分查找

int binarySearch(int* pArray , int low , int high , int value)

{

       if(NULL == pArray || low > high || low < 0 || high < 0)

       {

              return -1;

       }

       int middle;

       while( low <= high ) // "="取的原因是,同一个区间需要去做最后一次判定,否则遗漏一次判定操作

       {

         middle = low + (high - low)/2;

         if( pArray[middle] < value )

         {

                low = middle + 1;

         }

         else if( pArray[middle] > value )

         {

                high = middle - 1;

         }

         else

         {

                return middle;

         }

       }

       //如果发生low > high,肯定是找不到,返回-1

       return -1;

}

14

颜色填充

编写函数,实现许多图片编辑软件都支持的“填充颜色”功能。给定一个屏幕(以二维数组表示,元素为颜色值)、一个点和和一个新的颜色值,将新颜色值填入这个点的周围区域,直到原来的颜色值全部都改变。

输入:

5(宽) 5(高)

1(起点的横坐标) 3(起点的纵坐标)

1(新的颜色值)

输出:(整个区域填充后结果)

1 1 1 1 1

1 1 1 1 1

1 1 1 1 1

1 1 1 1 1

1 1 1 1 1

程序员面试金典

https://blog.csdn.net/qingyuanluofeng/article/details/54289332

分析:应该是经典的图形学算法:种子填充算法。该题目所要求的是从给定点开始,将整个屏幕区域的颜色都变为新的颜色。

      种子填充可以采用上下左右的递归来填充。对于当前点,将当前点填充好后,设置当前点访问过,然后获取当前点上下左右4个点,

         对这4个点中没有访问过的点都进行递归处理。

         可以以采用广度优先搜索来做。

 

代码:

const int MAXSIZE = 1000;

int gColorArray[MAXSIZE][MAXSIZE];//颜色数组

int gVisitArray[MAXSIZE][MAXSIZE];//访问数组,0表示未访问,1表示访问

//遍历的上下左右4个顶点走法

int gNext[4][2] =

{

       {0 , 1},

       {0 , -1},

       {-1, 0},

       {1,0}

};

 

//填充颜色

void fillColor(int x , int y , int width , int height, int newColor)

{

       int tempX ;

       int tempY;

       //遍历上下左右4个点

       for(int i = 0 ; i < 4 ; i++)

       {

              tempX = x + gNext[i][0];

              tempY = y + gNext[i][1];

              //判断候选点是否超出范围,是否访问过,如果已经访问,就不再处理

              if(tempX < 0 || tempX > width || tempY < 0 || tempY > height || 1 == gVisitArray[tempX][tempY])

              {

                     continue;

              }

              //接下来开始设置当前点已访问,并重新设置颜色,然后递归处理

              gVisitArray[tempX][tempY] = 1;

              gColorArray[tempX][tempY] = newColor;

              fillColor(tempX , tempY , width , height , newColor);

       }

}

15

寻找社交网站中的朋友路径

你会如何设计诸如Facebook或Linkedln的超大型社交网站?请设计一种算法,展示两个人之间的"连接关系"或"社交路径"(比如:,我->鲍勃->苏珊->杰森->你)

程序员面试金典

https://blog.csdn.net/qingyuanluofeng/article/details/54317016

书上解法:

          步骤1:如何在大数据的情况下,找到自己的朋友。

         人数非常多的时候,每个人的信息一般按照人的id分配在不同的机器上,比如按某种哈希散列后,存储在不同地方。

               最关键就是<人的id,机器id>,<机器id,人的id>,根据人的id想要获取人的信息,需要做以下处理:

               根据人的id找到机器id,根据机器id找到机器,获取机器上保存的<人的id,人>映射,获取人的信息。

               这是服务器类。

               步骤2:采用广度优先搜索,不用深度优先搜索的原因是两个人可能直接是朋友,如果深度优先搜索,可能搜索几百万结点

                       后发现不是,再继续搜,效果太差了

关键:

1

步骤1:如何在大数据的情况下,找到自己的朋友。

人数非常多的时候,每个人的信息一般按照人的id分配在不同的机器上,比如按某种哈希散列后,存储在不同地方。

最关键就是<人的id,机器id>,<机器id,人的id>,根据人的id想要获取人的信息,需要做以下处理:

根据人的id找到机器id,根据机器id找到机器,获取机器上保存的<人的id,人>映射,获取人的信息。

这是服务器类。

步骤2:采用广度优先搜索,不用深度优先搜索的原因是两个人可能直接是朋友,如果深度优先搜索,可能搜索几百万结点

              后发现不是,再继续搜,效果太差了

2

人类: 每个人包含自己的id,以及朋友id列表,而不是朋友列表,因为存储朋友列表会浪费空间

机器类:存储了<人的id,人>的映射,包含自身机器id

服务类:服务器类,存储<人的id,机器id>,<机器id,人的id>的映射

       服务类提供的最主要功能是根据用户id获取用户信息

3 扩展问题:

1)划分用户和机器,尽量按国家,城市,进行划分,减少跳转

2)找到同一机器上的多个朋友后,再跳转

3)广度优先搜索标记访问结点不要直接编辑数据,可以用散列表

4)优先选择自己朋友中拥有朋友个数较多的人作为起点遍历

5)搜索到何时放弃,即存在剪枝,比如最多深度为100时就不再搜索

 

代码:

//人,每个人包含自己的id,以及朋友id列表,而不是朋友列表,因为存储朋友列表会浪费空间

class Person

{

public:

       Person(int id):_id(id){}

       void addFriend(int id)

       {

              friends.push_back(id);

       }

       int _id;

       vector friends;

};

 

//机器,存储了<人的id,人>的映射,包含自身机器id

class Machine

{

public:

       Machine():_isNull(false){}

       //可以根据人的id获取人

       Person getPerson(int personId)

       {

              map::iterator it = personIdToPerson.find(personId);

              if(it != personIdToPerson.end())

              {

                     return it->second;

              }

              else

              {

                     return NULL;

              }

       }

private:

       map personIdToPerson;

       //机器包含机器id

       int _machineId;

public:

       bool _isNull;

};

 

//服务器类,存储<人的id,机器id>,<机器id,人的id>的映射

class Server

{

public:

       Server(){}

       void init(){}

       int getMachineId(int personId)

       {

              map::iterator it = personIdToMachineId.find(personId);

              if(it != personIdToMachineId.end())

              {

                     return it->second;

              }

              else

              {

                     return -1;

              }

       }

 

       Machine getMachine(int machineId)

       {

              map::iterator it = machineIdToMachine.find(machineId);

              if(it != machineIdToMachine.end() )

              {

                     return it->second;

              }

              else

              {

                     Machine machine;

                     machine._isNull = true;

                     return machine;

              }

       }

 

       //服务类提供的最主要功能是根据用户id获取用户信息

       Person getPersonByPersonId(int personId)

       {

              int machineId = getMachineId(personId);

              if(-1 == machineId)

              {

                     return NULL;

              }

              Machine machine = getMachine(machineId);

              Person person = machine.getPerson(personId);

              return person;

       }

private:

       map personIdToMachineId;

       map machineIdToMachine;

};

16

找出已排序数组经过旋转后某个元素

给定一个排序后的数组,包含n个整数,但这个数组已经被旋转过很多次,次数不详。请编写代码找出数组中的某个元素。可以假定数组元素原先是按照从小到大的顺序排列的。

程序员面试金典

https://blog.csdn.net/qingyuanluofeng/article/details/54349066

17

有个排序后的字符串数组,其中散布这一些空字符串,编写一个方法,找出给定字符串的位置

程序员面试金典

https://blog.csdn.net/qingyuanluofeng/article/details/54349154

18

设计一个方法,找出任意指定单词在一本书中的出现频率

程序员面试金典

https://blog.csdn.net/qingyuanluofeng/article/details/54578917

19

设计一个算法,找出数组中两数之和为指定值的所有整数对。

程序员面试金典

https://blog.csdn.net/qingyuanluofeng/article/details/54583254

20

有个内含单词的超大文本文件,给定任意两个单词,找出在这个文件中这两个单词的最短距离(也即相隔几个单词)。有办法在O(1)时间里完成搜索操作吗?解法的空间复杂度如何?

程序员面试金典

https://blog.csdn.net/qingyuanluofeng/article/details/54603976

21

3Sum

Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.

Note: The solution set must not contain duplicate triplets.

For example, given array S = [-1, 0, 1, 2, -1, -4],

A solution set is:

[

  [-1, 0, 1],

  [-1, -1, 2]

]

triplets:三元组

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/54782732

22

3Sum Closest

Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. You may assume that each input would have exactly one solution.

For example, given array S = {-1 2 1 -4}, and target = 1.

The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).

翻译:

这个是找到三个数的和要最接近给定值。

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/54782805

23

4Sum

Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.

Note: The solution set must not contain duplicate quadruplets.

For example, given array S = [1, 0, -1, 0, -2, 2], and target = 0.

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/54798862

24

Remove Element

Given an array and a value, remove all instances of that value in place and return the new length.

Do not allocate extra space for another array, you must do this in place with constant memory.

The order of elements can be changed. It doesn't matter what you leave beyond the new length.

Example:

Given input array nums = [3,2,2,3], val = 3

Your function should return length = 2, with the first two elements of nums being 2.

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/54848487

25

Search in Rotated Sorted Array

Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.

(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2).

You are given a target value to search. If found in the array return its index, otherwise return -1.

You may assume no duplicate exists in the array.

分析:

这是程序员面试金典的一道题目。是在旋转数组中查找一个元素。

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/54926088

26

Search for a Range

Given an array of integers sorted in ascending order, find the starting and ending position of a given target value.

Your algorithm's runtime complexity must be in the order of O(log n).

If the target is not found in the array, return [-1, -1].

For example,

Given [5, 7, 7, 8, 8, 10] and target value 8,

return [3, 4].

Leeode

https://blog.csdn.net/qingyuanluofeng/article/details/54926758

27

Search Insert Position

Given a sorted array and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order.

You may assume no duplicates in the array.

Here are few examples.

[1,3,5,6], 5 → 2

[1,3,5,6], 2 → 1

[1,3,5,6], 7 → 4

[1,3,5,6], 0 → 0

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/54927050

28

Valid Sudoku

Determine if a Sudoku is valid, according to: Sudoku Puzzles - The Rules.

The Sudoku board could be partially filled, where empty cells are filled with the character '.'.

A partially filled sudoku which is valid.

Note:

A valid Sudoku board (partially filled) is not necessarily solvable. Only the filled cells need to be validated.

分析:

实质就是根据现有数独中已经填充的数字,计算是否有解。

数独中每一行和每一列必须包含1~9的数字

3*3的数组中必须包含1~9每个数字。

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/54928387

29

Sudoku Solver

Write a program to solve a Sudoku puzzle by filling the empty cells.

Empty cells are indicated by the character '.'.

You may assume that there will be only one unique solution.

A sudoku puzzle...

...and its solution numbers marked in red.

分析:

这是搜索是否有解的问题,

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/54930149

30

Sort Colors

Given an array with n objects colored red, white or blue, sort them so that objects of the same color are adjacent, with the colors in the order red, white and blue.

Here, we will use the integers 0, 1, and 2 to represent the color red, white, and blue respectively.

Note:

You are not suppose to use the library's sort function for this problem.

click to show follow up.

Follow up:

A rather straight forward solution is a two-pass algorithm using counting sort.

First, iterate the array counting number of 0's, 1's, and 2's, then overwrite array with total number of 0's, then 1's and followed by 2's.

Could you come up with an one-pass algorithm using only constant space?

分析:颜色摆放问题。红白蓝三种颜色代表的数组,分别对应012,现在要使得

数组中相同颜色的相邻。不能使用系统自带的排序函数。

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/55000030

31

Word Search

Given a 2D board and a word, find if the word exists in the grid.

The word can be constructed from letters of sequentially adjacent cell, where "adjacent" cells are those horizontally or vertically neighboring. The same letter cell may not be used more than once.

For example,

Given board =

[

  ['A','B','C','E'],

  ['S','F','C','S'],

  ['A','D','E','E']

]

word = "ABCCED", -> returns true,

word = "SEE", -> returns true,

word = "ABCB", -> returns false.

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/55002974

32

Search in Rotated Sorted Array II

Follow up for "Search in Rotated Sorted Array":

What if duplicates are allowed?

Would this affect the run-time complexity? How and why?

Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.

(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2).

Write a function to determine if a given target is in the array.

The array may contain duplicates.

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/55006880

33

Best Time to Buy and Sell Stock

Contributors: Admin

Say you have an array for which the ith element is the price of a given stock on day i.

If you were only permitted to complete at most one transaction (ie, buy one and sell one share of the stock), design an algorithm to find the maximum profit.

Example 1:

Input: [7, 1, 5, 3, 6, 4]

Output: 5

max. difference = 6-1 = 5 (not 7-1 = 6, as selling price needs to be larger than buying price)

Example 2:

Input: [7, 6, 4, 3, 1]

Output: 0

In this case, no transaction is done, i.e. max profit = 0.

分析:给定一个数组,模拟股票价格,要求获取最大利润。也就是从数组中选取两个元素,并且满足较小的元素在前面,较大的元素在后面,

求这样一个差值最大的两个元素。

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/55227456

34

Best Time to Buy and Sell Stock II

Say you have an array for which the ith element is the price of a given stock on day i.

Design an algorithm to find the maximum profit. You may complete as many transactions as you like

(ie, buy one and sell one share of the stock multiple times). However, you may not engage in multiple

transactions at the same time (ie, you must sell the stock before you buy again).

分析:此题的意思是允许多次买入后再抛出股票。每次买入股票前必须先抛出之前买的。

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/55229904

35

Word Ladder

Given two words (beginWord and endWord), and a dictionary's word list, find the length of shortest transformation sequence from beginWord to endWord, such that:

Only one letter can be changed at a time.

Each transformed word must exist in the word list. Note that beginWord is not a transformed word.

For example,

Given:

beginWord = "hit"

endWord = "cog"

wordList = ["hot","dot","dog","lot","log","cog"]

As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog",

return its length 5.

Note:

Return 0 if there is no such transformation sequence.

All words have the same length.

All words contain only lowercase alphabetic characters.

You may assume no duplicates in the word list.

You may assume beginWord and endWord are non-empty and are not the same.

分析:这是求最短字符串长度。

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/55271936

36

Surrounded Regions

Given a 2D board containing 'X' and 'O' (the letter O), capture all regions surrounded by 'X'.

A region is captured by flipping all 'O's into 'X's in that surrounded region.

For example,

X X X X

X O O X

X X O X

X O X X

After running your function, the board should be:

X X X X

X X X X

X X X X

X O X X

输入:

4(行) 4(列)

X X X X

X O O X

X X O X

X O X X

输出:

X X X X

X X X X

X X X X

X O X X

关键

1 分析:此题实际上找到四周都是"X"的"O",并把这些"O"替换为"X"。

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/55353384

37

Find Minimum in Rotated Sorted Array

Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.

(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2).

Find the minimum element.

You may assume no duplicate exists in the array.

分析:找到旋转数组中最小的元素。之前是做了找到旋转数组中某个元素是否存在。

这里假设没有重复。

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/56025453

38

Find Peak Element

A peak element is an element that is greater than its neighbors.

Given an input array where num[i] ≠ num[i+1], find a peak element and return its index.

The array may contain multiple peaks, in that case return the index to any one of the peaks is fine.

You may imagine that num[-1] = num[n] = -∞.

For example, in array [1, 2, 3, 1], 3 is a peak element and your function should return the index number 2.

click to show spoilers.

Credits:

Special thanks to @ts for adding this problem and creating all test cases.

分析:题目是为了寻找一个高峰元素,所谓高峰元素要大于两边元素,如果有多处高峰,返回其中任意的一个下标。

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/56047747

39

Two Sum II - Input array is sorted

Given an array of integers that is already sorted in ascending order, find two numbers such that they add up to a specific target number.

The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are not zero-based.

You may assume that each input would have exactly one solution and you may not use the same element twice.

Input: numbers={2, 7, 11, 15}, target=9

Output: index1=1, index2=2

分析:在给定升序的数组中,返回两个相加和等于指定值得下标,下标都是从1开始的,第一个下标

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/56276361

40

Number of Islands

Given a 2d grid map of '1's (land) and '0's (water), count the number of islands. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water.

Example 1:

11110

11010

11000

00000

Answer: 1

Example 2:

11000

11000

00100

00011

Answer: 3

分析:这个实际上就是求被水(0)分割的1的块数

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/56304174

41

Minimum Size Subarray Sum

Given an array of n positive integers and a positive integer s, find the minimal length of a contiguous subarray of which the sum ≥ s. If there isn't one, return 0 instead.

For example, given the array [2,3,1,2,4,3] and s = 7,

the subarray [4,3] has the minimal length under the problem constraint.

click to show more practice.

More practice:

If you have figured out the O(n) solution, try coding another solution of which the time complexity is O(n log n).

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/56485513

42

Contains Duplicate

Given an array of integers, find if the array contains any duplicates.

Your function should return true if any value appears at least twice in the array,

and it should return false if every element is distinct.

分析:判断数组是否含有重复元素。

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/56495258

43

Contains Duplicate II

Given an array of integers and an integer k, find out whether there are two distinct

indices i and j in the array such that nums[i] = nums[j] and the absolute difference

between i and j is at most k.

分析:给定整数和整数k,找到是否有两个不同的下标i和j,使得nums[i]=nums[j],并且i和j的查找最多不超过k。

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/56495697

44

Contains Duplicate III

Given an array of integers, find out whether there are two distinct indices i and j

in the array such that the absolute difference between nums[i] and nums[j] is at most t

and the absolute difference between i and j is at most k.

分析:也就是说要寻找任意元素对应的下标i和j,满足i和j的差的绝对值<=k,两个数值的差值<=t

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/56498897

45

First Bad Version

You are a product manager and currently leading a team to develop a new product. Unfortunately,

the latest version of your product fails the quality check. Since each version is developed based on the previous version, all the versions

after a bad version are also bad.

Suppose you have n versions [1, 2, ..., n] and you want to find out the first bad one,

which causes all the following ones to be bad.

You are given an API bool isBadVersion(version) which will return whether version is bad.

Implement a function to find the first bad version. You should minimize the number of calls to the API.

分析:发现一个版本号是否是坏的版本,确保调用次数最少

被调函数要实现根据给定的版本号,找到首先是最坏的版本。最坏的版本号的特点是当前及其之后版本号都是属于坏的版本。

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/57406047

46

Valid Perfect Square

Given a positive integer num, write a function which returns True if num is a perfect square else False.

Note: Do not use any built-in library function such as sqrt.

Example 1:

Input: 16

Returns: True

Example 2:

Input: 14

Returns: False

分析:给定一个正整数,判定它是否是一个完全平方数。不能使用内置的sqrt。

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/59481236

47

Water and Jug Problem

You are given two jugs with capacities x and y litres. There is an infinite amount of water supply available. You need to determine whether it is possible to measure exactly z litres using these two jugs.

If z liters of water is measurable, you must have z liters of water contained within one or both buckets by the end.

Operations allowed:

Fill any of the jugs completely with water.

Empty any of the jugs.

Pour water from one jug into another till the other jug is completely full or the first jug itself is empty.

Example 1: (From the famous "Die Hard" example)

Input: x = 3, y = 5, z = 4

Output: True

Example 2:

Input: x = 2, y = 6, z = 5

Output: False

分析:此题是给定两个容量分别为x和y的杯子,问是否能够测量出容积为z的水。

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/59745816

48

Guess Number Higher or Lower

We are playing the Guess Game. The game is as follows:

I pick a number from 1 to n. You have to guess which number I picked.

Every time you guess wrong, I'll tell you whether the number is higher or lower.

You call a pre-defined API guess(int num) which returns 3 possible results (-1, 1, or 0):

-1 : My number is lower

 1 : My number is higher

 0 : Congrats! You got it!

Example:

n = 10, I pick 6.

Return 6.

分析:实际上就是猜数字游戏。给定n,求猜别人拿的是哪个数字。

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/59752076

49

如何从数组中找出满足 a+b=c+d 的两个数对

给定一个数组,找出数组中是否有两个数对(a, b)和(c, d), 使得 a+b=c+d,其中, a、b、c和d

是不同的元素。如果有多个答案,打印任意一个即可。例如给定数组:

[3, 4, 7, 10, 20, 9, 8],可以找到两个数对(3, 8)和(4, 7),使得

3+8=4+7

Python程序员面试算法宝典

https://blog.csdn.net/qingyuanluofeng/article/details/91351998

50

如何找出旋转数组的最小元素

把一个有序数组最开始的若干个元素搬到数组的末尾,称之为数组的旋转。

输入一个排好序的数组的一个旋转,输出旋转数组的最小元素。例如:

数组[3,4,5,1,2]为数组[1,2,3,4,5]的一个旋转,该数组的最小值为1。

Python程序员面试算法宝典

https://blog.csdn.net/qingyuanluofeng/article/details/92384916

51

如何求数组中两个元素的最小距离

给定一个数组,数组中含有重复元素,给定两个数字num1和num2,求这两个数字在

数组中出现的位置的最小距离。

Python程序员面试算法宝典

https://blog.csdn.net/qingyuanluofeng/article/details/92727422

52

如何求数组中绝对值最小的数

有1个升序排列的数组,数组中可能有正数、负数或0,求数组中元素的绝对值最小的数,

例如:数组[-10, -5, -2, 7, 15, 50],该数组中绝对值最小的数是-2。

Python程序员面试算法宝典

https://blog.csdn.net/qingyuanluofeng/article/details/92801267

53

如何寻找最多的覆盖点

坐标轴上从左到右依次的点为a[0], a[1], a[2], ..., a[n-1],

设一根木棒的长度为L,求L最多能覆盖坐标轴的几个点?

Python程序员面试算法宝典

https://blog.csdn.net/qingyuanluofeng/article/details/93401148

54

如何求解迷宫问题

给定一个大小为N*N的迷宫,一只老鼠需要从迷宫的左上角(

对应矩阵的[0][0])走到迷宫的右下角(对应矩阵的[N-1][N-1]),

老鼠只能向两方向移动:向右或向下。在迷宫中,0表示没有路

(是死胡同),1表示有路。例如: 给定下面的迷宫:

1   0   0   0

1   1   0   1

0   1   0   0

1   1   1   1

途中标粗的路径就是一条合理的路径。

请给出算法来找到这么一条合理路径。

Python程序员面试算法宝典

https://blog.csdn.net/qingyuanluofeng/article/details/93660114

55

如何从三个有序数组中找出它们的公共元素

给定以非递减顺序排序的三个数组,找出这三个数组中的所有公共元素。例如,

给出下面三个数组:

ar1 = [2, 5, 12, 20, 45, 85]

ar2 = [16, 19, 20, 85, 200]

ar3 = [3, 4, 15, 20, 39, 72, 85, 190]

那么这三个数组的公共元素为[20, 85]。

Python程序员面试算法宝典

https://blog.csdn.net/qingyuanluofeng/article/details/93662500

56

如何判断两个字符串是否为换位字符串

换位字符串是指组成字符串的字符相同,但位置不同。例如:由于字符串"aaaabbc" 与 "abcbaaa"就是相同的字符所组的,因此它们是换位字符。

Python程序员面试算法宝典

https://blog.csdn.net/qingyuanluofeng/article/details/94303630

57

如何判断两个字符串的包含关系

给定由字母组成的字符串s1和s2,其中,s2中字母的个数少于s1,如何判断s1是否包含

s2? 即出现在s2中的字符在s1中都存在。

例如s1="abcdef", s2="acf",那么s1就包含s2;

如果s1="abcdef", s2="acg",那么s1就不包含s2,因为s2

中有'g',但是s1中没有'g'

Python程序员面试算法宝典

https://blog.csdn.net/qingyuanluofeng/article/details/94305574

58

如何判断一个字符串是否包含重复字符

判断一个字符串是否包含重复字符。例如: 'good'就包含重复字符'0',

而'abc'就不包含重复字符

Python程序员面试算法宝典

https://blog.csdn.net/qingyuanluofeng/article/details/94543155

59

如何查找到达目标词的最短链长度

给定一个词典和两个长度相同的"开始"和"目标"的单词。

找到从开始到姆博阿的最小链的长度。如果它存在,

那么这条链中的相邻单词只有一个字符不同,

而链中的每个单词都是有效单词,即它存在于词典中。

可以假设词典中存在目标字,所有词典的长度相同。

例如:

给定一个单词词典为:

[pooN, pbcc, zamc, poIc, pbca, pbIc, poIN]

start = ToolN

target = pbca

输出结果为: 7

因为: TooN(start) - pooN - poIN - poIc - pbIc - pbcc - pbca(target)。

Python程序员面试算法宝典

https://blog.csdn.net/qingyuanluofeng/article/details/95906956

60

如何判断一个自然数是否是某个数的平方

设计一个算法,判断给定的一个数n是否是某个数的平方,不能使用开方运算。

例如16就满足条件,因为它是4的平方,而15则不满足条件,因为不存在

一个数使得其平方的值为15.

Python程序员面试算法宝典

https://blog.csdn.net/qingyuanluofeng/article/details/95918112

61

如何在不能使用库函数的条件下计算n的平方根

给定一个数n,求出它的平方根,比如16的平方根是4.要求不能使用库函数。

Python程序员面试算法宝典

https://blog.csdn.net/qingyuanluofeng/article/details/96723712

62

黑白图像

输入一个n*n的黑白图像(1表示黑色,0表示白色),任务是统计其中八连块的个数。如果两个黑盒子有公共边或者公共顶点,就说它们属于同一个八连块。

如图所示,有3个八连块

输入:

6

100100

001010

000000

110000

111000

010100

输出:

3

算法竞赛入门经典

https://blog.csdn.net/qingyuanluofeng/article/details/47730863

63

迷宫
一个网格迷宫由n行m列单元格组成,每个单元格要么是空地(用1表示),要么是障碍物(用0表示)。你的任务是找一条从起点到终点的最短移动序列,其中UDLR分别

表示往上、下、左、右移动到相邻单元格。任何时候都不能在障碍格中,也不能走到迷宫之外。起点和终点保证是空地。n,m<=100。

算法竞赛入门经典

https://blog.csdn.net/qingyuanluofeng/article/details/47730893

64

迷宫路径
一个网格迷宫由n行m列单元格组成,每个单元格要么是空地(用1表示),要么是障碍物(用0表示)。你的任务是找一条从起点到终点的最短移动序列,其中UDLR分别

表示往上、下、左、右移动到相邻单元格。任何时候都不能在障碍格中,也不能走到迷宫之外。起点和终点保证是空地。n,m<=100。

算法竞赛入门经典

https://blog.csdn.net/qingyuanluofeng/article/details/47730937

65

除法

输入正整数,按从小到大的顺序输出所有形如abcde/fghij=n的表达式,其中a~j恰好为数字0~9的一个排列,2<=n<=79.

输入:

62

输出:

79546/01283=62

94736/01528=62

算法竞赛入门经典

https://blog.csdn.net/qingyuanluofeng/article/details/47731045

66

最大乘积

算法竞赛入门经典

https://blog.csdn.net/qingyuanluofeng/article/details/47731081

67

分数拆分

算法竞赛入门经典

https://blog.csdn.net/qingyuanluofeng/article/details/47731123

68

双基回文数

如果一个正整数n至少在两个不同的进位制b1和b2下都是回文数(2<=b1,b2<=10),则称n是双基回文数(注意,回文数不能包含前导0)。输入正整数S<10^6,输出比

S大的最小双基回文数>

输入:1600000(1632994)

输出:1632995

算法竞赛入门经典

https://blog.csdn.net/qingyuanluofeng/article/details/47731141

69

倒水问题

有装满水的6升杯子、空的3升杯子和一升杯子,3个杯子中都没有刻度。在不使用其他道具的情况下,是否可以量出4升的水呢?

输入:

6(满杯水所在的刻度) 3 1

输出:

(6,0,0)->(3,3,0)->(3,2,1)->(4,2,0)

算法竞赛入门经典

https://blog.csdn.net/qingyuanluofeng/article/details/47746957

70

八数码问题

编号为1~8的8个正方形滑块被摆成3行3列(有一个格子空留),如图所示。每次可以把与空格相邻的滑块(有公共边才算相邻)移到空格中,而它原来的位置就称为了

新的空格。给定初始局面和目标局面(用0表示空格格),你的任务是计算出最少的移动步数。如果无法达到目标局面,则输-1.

2     6     4     8  1    5

1     3     7       7  3    6

       5     8     4     2

算法竞赛入门经典

https://blog.csdn.net/qingyuanluofeng/article/details/47746983

71

八数码问题之哈希去重

输入:

2 6 4 1 3 7 0 5 8

8 1 5 7 3 6 4 0 2

输出:

31

算法竞赛入门经典

https://blog.csdn.net/qingyuanluofeng/article/details/47746995

72

八数码问题之stl

1set vis,这样只需要调用if(vis.count(s))来判断s是否在集合vis中,并用vis.insert(s)加入集合,用vis.remove(s)从集合中移除s。

问题:并不是所有类型的State都可以作为set中的元素类型。set的元素必须定义"<"运算符,C语言原生的数组(包括字符数组)却不行。

2如果数组不能转化为整数,自己声明结构体,重载函数调用符比较状态。下面中,整数a和b分别是两个状态在状态数组st中的下标,在比较时直接使用memcpy来比较整个

内存块

输入:

2 6 4 1 3 7 0 5 8

8 1 5 7 3 6 4 0 2

输出:

31

算法竞赛入门经典

https://blog.csdn.net/qingyuanluofeng/article/details/47747019

73

二分查找

本质:有序表中使用二分查找,log2(1000)

深入:

如果数组中多个元素都是v,上面的函数返回的是中间的一个。能不能呢个求出值等于v的完整区间呢?

下面的程序当v存在时返回它出现的第一个位置。如果不存在,返回这样一个下标i:在此处插入v(原来的元素A[i],A[i+1],..全部往后移动一个位置)后序列仍然有序

思路

排序后:

0 1 3 4 6 7 9 9

输入:

8

1 9 6 3 4 7 9 0

3

8

1 9 6 3 4 7 9 0

5

输出:

2

-1

算法竞赛入门经典

https://blog.csdn.net/qingyuanluofeng/article/details/47747225

74

二分查找之lowerBound

注意:对于二分查找的一个系列,high都是用数组长度来计算,真正是取不到的

如果数组中多个元素都是v,上面的函数返回的是中间的一个。能不能呢个求出值等于v的完整区间呢?

下面的程序当v存在时返回它出现的第一个位置。如果不存在,返回这样一个下标i:在此处插入v(原来的元素A[i],A[i+1],..全部往后移动一个位置)后序列仍然有序

输入:

8

0 1 3 4 6 7 9 9

5

 

8

0 1 4 4 4 4 9 9

4

输出:

4

2

算法竞赛入门经典

https://blog.csdn.net/qingyuanluofeng/article/details/47747247

75

二分查找之upperBound


写一个upperBound程序,当v存在时返回它出现的最后一个位置的后面的一个位置。如果不存在,返回这样一个下标i:在此处插入v(原来的元素A[i],A[i+1],..全部

往后移动一个位置)后序列仍然有序。

 

输入:

8

0 1 3 4 6 7 9 9

5

 

8

0 1 3 4 4 4 9 9

4

 

8

0 3 3 4 4 4 9 9

3

输出:

4

6

算法竞赛入门经典

https://blog.csdn.net/qingyuanluofeng/article/details/47747257

76

二分查找之范围统计

给出n个整数xi和m个询问,对于每个询问(a,b),输出闭区间[a,b]内的整数xi的个数。

输入:

8

0 1 3 4 6 7 9 9

3 9

输出:

6

算法竞赛入门经典

https://blog.csdn.net/qingyuanluofeng/article/details/47747273

77

非线性方程求根

一次向银行借a元钱,分b月还清。如果需要每月还c元,月利率是多少(按复利率计算)?例如借2000元,分4个月每月还510,则月利率为0.797%。答案应不超过100%。
输入:

2000 4 510

输出:

0.797%

算法竞赛入门经典

https://blog.csdn.net/qingyuanluofeng/article/details/47775495

78

统计书中的单词及出现次数,实现一个数据结构进行存储

编程珠玑

https://blog.csdn.net/qingyuanluofeng/article/details/54647029

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

参考:
[1]计算机考研--机试指南,王道论坛 组编
[2]剑指offer
[3]算法设计与分析
[4]编程之美
[5]程序员面试金典
[6]leecode
[7]Python
程序员面试算法宝典
[8]刘汝佳算法竞赛入门经典
[9]算法导论
[10]编程珠玑

 

你可能感兴趣的:(算法,64式)