【【【可能有代码是借鉴大神的,如果有问题会删掉并道歉!】】】
1.青蛙跳杯子
蓝桥杯 试题 历届试题 青蛙跳杯子
题目:http://lx.lanqiao.cn/problem.page?gpid=T448
package 练习;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
public class _44青蛙跳杯子_ {
static String inStr,targetStr;
static Map<String,Boolean> mapp=new HashMap<String,Boolean>();
public static void main(String[] args) throws IOException {
BufferedReader bReader = new BufferedReader(new InputStreamReader(System.in));
inStr = bReader.readLine();
targetStr = bReader.readLine();
bReader.close();
System.out.println(bfs());
}
public static int bfs()
{
//新建队列+新建头结点+头结点入队列+头结点标记hashmap
Queue<Node> queue =new LinkedList<Node>();
Node now = new Node(inStr,0);
queue.add(now);
mapp.put(now.string,true);
//当队列非空
while(queue.size()!=0)
{
//头结点出队列
now=queue.poll();
//判断此时的结点是否满足最终的结果
if(isOk(now.string))
{
return now.step;
}
//当前头结点的一些信息
char s[]=now.string.toCharArray();
int stepp=now.step;
//以now为头结点的各种情况(各个青蛙都跳)
for(int i=0;i<s.length;i++)
{
//杯子跳过
if(s[i]=='*')
continue;
//当前青蛙可跳的方向
for(int j=-3;j<=3;j++)
{
if(i+j<0||i+j>=s.length||j==0||s[i+j]!='*')
continue;
s=swap(s,i,i+j);
Node node= new Node (String.valueOf(s),stepp+1);
if(!mapp.containsKey(node.string))
{
queue.add(node);
mapp.put(node.string,true);
}
//当前青蛙跳完要回归原样,下一个青蛙跳
s=swap(s,i,i+j);
}
}
}
return -1;
}
public static char[] swap(char [] s,int i,int j)
{
char temp;
temp=s[i];
s[i]=s[j];
s[j]=temp;
return s;
}
public static boolean isOk(String s)
{
if (targetStr.equalsIgnoreCase(s)) {
return true;
}
else {
return false;
}
}
}
class Node
{
String string;
int step;
public Node(String string,int step)
{
this.string=string;
this.step=step;
}
}
1.Map接口,HashMap实现,<k,v>
新建: Map<String,Boolean> mapp=new HashMap<String,Boolean>();
添加: mapp.put(now.string,true);
查询: mapp.containsKey(node.string)
2.队列, queue接口,LinkedList实现
新建: Queue<Node> queue =new LinkedList<Node>();
进队列: queue.add(now);
出队列: now=queue.poll();
3.字符数组
字符串变数组:char s[]=now.string.toCharArray();
数组变字符串:String str=String.valueOf(s)
2.九宫重排
题目:http://lx.lanqiao.cn/problem.page?gpid=T42
package 练习;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import java.util.Scanner;
public class _19九宫重排_ {
static String start,end,now;
static Map<String,Integer> mapp=new HashMap<String,Integer>();
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
start = scan.next();
end = scan.next();
System.out.print(bfs());
}
public static int bfs()
{
//新建队列+头结点入队列+map记录
Queue <String> queue=new LinkedList<String>();
queue.add(start);
mapp.put(start, 0);
while(queue.size()!=0)
{
//头结点出队列
now=queue.poll();
//判断终止
if (now.equals(end))
{
return mapp.get(now);
}
//处理头结点
char s[]=now.toCharArray();
int temp=0;
int[] d = {-3,3,-1,1};//方向数组,分别表示上下左右
for(int k=0;k<s.length;k++)
{
if(s[k]=='.')
{
temp=k;
break;
}
}
for(int i=0;i<4;i++)
{
//约束条件
if(temp+d[i]<0||temp+d[i]>8||((temp+d[i])%3!=temp%3&&(temp+d[i])/3!=temp/3))
continue;
s=swap(s,temp,temp+d[i]);
//判断新结点并入队列
if(!mapp.containsKey(String.valueOf(s)))
{
mapp.put(String.valueOf(s), mapp.get(now)+1);
queue.add(String.valueOf(s));
}
//恢复原字符串
s=swap(s,temp,temp+d[i]);
}
}
return 0;
}
public static char [] swap(char[] s,int i,int j)
{
char tempp;
tempp=s[i];
s[i]=s[j];
s[j]=tempp;
return s;
}
}
1.这个bfs框架和上面那个基本相同
2.不同之处:用HashMap的<k,v>里的value来记录步数,去掉了Node类
取HashMap中的value值: mapp.get(now)
(其中now为key值)
3.bfs能搜到所有结果,且第一次输出的结果为最小值(?)
3.学霸的迷宫
题目:http://lx.lanqiao.cn/problem.page?gpid=T291
package 算法提高;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
import java.util.Stack;
public class _147学霸的迷宫
{ static int a[][];
//static int b[][]={{-1,0},{1,0},{0,-1},{0,1}};//这个顺序是不能随便调换的,是为了满足字典顺序的需求DLRU
static int b[][]={{1,0},{0,-1},{0,1},{-1,0}};
public static void main(String[]agrs)
{
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
int m=sc.nextInt();
a=new int[n][m];
for(int i=0;i<n;i++)
{
String s=sc.next();
for(int j=0;j<m;j++)
a[i][j]=s.charAt(j)-'0';
}//输入细节就不多讲了
Queue<P> queue=new LinkedList<>(); //创建队列
queue.add(new P(0,0,null,'n')); //把第一个加入队列 加入起点,P这个类的信息见最下面
a[0][0]=1;//置1说明不可访问;
boolean sign=true;
P tail=null;//指向终点
while(!queue.isEmpty()&&sign) //while
{
P p=queue.poll();//出一个头节点 //第一个出队列
int x=p.x;
int y=p.y; //对刚才出队列的点进行处理
for(int i=0;i<4;i++) //for循环
{
int x1=x+b[i][0];
int y1=y+b[i][1];
if(x1<0||x1>=n||y1<0||y1>=m||a[x1][y1]==1)//排除不合理 continue
continue;
a[x1][y1]=1;//这个要注意
queue.add(new P(x1,y1,p,get(i))); //把新点加入队列
//x1,y1即为这点的位置信息,p即指向上一个节点,get(i)即为由p到当前点的方向
if(x1==n-1&&y1==m-1) //如果找到终点,则终止搜索
{
tail=new P(x1,y1,p,get(i));//tail的作用
sign=false;//终止标志
break;//退出子循环
}
}
}
queue=null;
Stack<P> stack=new Stack<>();
P p=tail;
while(p.last!=null)//从tail开始一个一个开始入栈;如果p.last为null则说明已经到了起点
{
stack.push(p);
p=p.last;
}
System.out.println(stack.size());
while(!stack.isEmpty())
{
System.out.print(stack.pop().d);//依次出栈即可
}
}
static char get(int index)//满足字典顺序要求
{
switch(index)
{
case 0:return 'D';
case 1:return 'L';
case 2:return 'R';
case 3:return 'U';
}
return ' ';
}
}
class P//实质上就是一个链表的node
{
int x;
int y;
P last;//指向上一个位置,学c的可以看成是指针
char d;//记录由上一个为到到当前位置的转向
P(int x,int y,P last,char d)
{
this.x=x;
this.y=y;
this.last=last;
this.d=d;
}
}
4.迷宫
题目可见试题D:迷宫
package 第二次;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class _C迷宫 {
static boolean[][] vis = new boolean[60][60];
static HashSet <node> sets = new HashSet<node>();
static int m=30,n=50;
static char[][] mapp;
public static void main(String[] args) throws FileNotFoundException {
Scanner in = new Scanner (new File("/1.课程(项目相关)/蓝桥杯训练/2019A/maze.txt"));
mapp= new char[m+1][n+1];
for(int i=0;i<m;i++)
{
String temp=in.next(); //读取一行
mapp[i]=temp.toCharArray();
}
bfs();
}
public static void bfs()
{
int zuobiao[][] = new int[][] {{1,0},{0,-1},{0,1},{-1,0}};
String fangxiang[] = new String [] {"D","L","R","U"};
int newx,newy;
Queue<node> que = new LinkedList<node>(); //建队列
node first= new node(0,0,"",0);
que.add(first); //头结点入队列
while(que.size()!=0)
{
node now = que.peek();
que.poll();
vis[now.x][now.y]=true;
if(now.x==m-1 && now.y==n-1)
{
System.out.print(now.path);
return;
}
for(int i=0;i<4;i++)
{
newx=now.x+zuobiao[i][0];
newy=now.y+zuobiao[i][1];
if(newx<0||newy<0||newx>=m||newy>=n||mapp[newx][newy]=='1'||vis[newx][newy]==true)
{
continue;
}
node newnode = new node(newx,newy,now.path+fangxiang[i],now.step+1);
que.add(newnode);
}
}
}
}
class node
{
String path;
int step=0;
int x,y;
node(int x,int y ,String path,int step)
{
this.x=x;
this.y=y;
this.path=path;
this.step=step;
}
}
5.二叉树的层序遍历
class Solution {
public List<List<Integer>> resList = new ArrayList<List<Integer>>();
public List<List<Integer>> levelOrder(TreeNode root) {
checkFun02(root);
return resList;
}
public void checkFun02(TreeNode node) {
if (node == null) return;
// 新建队列+头结点入队列
Queue<TreeNode> que = new LinkedList<TreeNode>();
que.offer(node);
// 所有数据通过队列进行处理
while (!que.isEmpty()) {
// 通过len记录每一层
// 对每一层进行处理,由于上一层已经都poll出去了,下一层还没开始,
// 所以当前len就是本层数量
List<Integer> itemList = new ArrayList<Integer>();
int len = que.size();
// 处理当前层
while (len > 0) {
// 本层节点相关处理:出队列,入结果列表
TreeNode tmpNode = que.poll();
itemList.add(tmpNode.val);
// 下层结果预处理,进队列
if (tmpNode.left != null) que.offer(tmpNode.left);
if (tmpNode.right != null) que.offer(tmpNode.right);
// 本层数量--
len--;
}
//本层处理完了,放入结果列表
resList.add(itemList);
}
}
}
6.二找树左下角的值
class Solution {
public int findBottomLeftValue(TreeNode root) {
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
int res = 0;
while (!queue.isEmpty()) {
int size = queue.size();
for (int i = 0; i < size; i++) {
TreeNode poll = queue.poll();
if (i == 0) {
res = poll.val;
}
if (poll.left != null) {
queue.offer(poll.left);
}
if (poll.right != null) {
queue.offer(poll.right);
}
}
}
return res;
}
}