leetcode 整数反转+基于BFS的八数码问题算法 c++

leetcode 整数反转+基于BFS的八数码问题算法 c++

leetcode 整数反转

难度:简单

给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。

示例 1:

输入: 123
输出: 321

注意:

假设我们的环境只能存储得下 32 位的有符号整数,则其数值范围为 [−2^31, 2^31 − 1]。请根据这个假设,如果反转后整数溢出那么就返回 0。

这个题目实现倒是简单,重点在于反转后整数溢出那么就返回 0,这里有两种实现思路;’

思路一就是通过long类型数值范围判断反转后整数是否溢出。(也有意见说题目已经假设环境不能使用long类型,所以这种思路是不对的,但是提交通过)

代码:

int reverse(int x){
    int max=0x7fffffff;//整型数据int的上界
	long a=0;
	for(; x!=0; ){
        a = a*10+x%10;
		x = x/10;
	}
    return (a > max || a < (-1 * (max + 1))) ? 0 : a;
}

思路二是把y与INT_MAX/10和INT_MIN/10比较,将范围缩小10倍之后比较可以有效防止最后y的溢出错误。

代码:

int reverse(int x) {
        int y = 0;
        while(x/10 != 0 ){
            y = y*10+x%10;
            x = x/10;
            if(y>INT_MAX/10||y<INT_MIN/10)  return 0;
        }
        if((y==INT_MAX/10&&x>INT_MAX%10)||(y==INT_MIN/10&&x<INT_MIN%10)) return 0;
        y = y*10+x%10;
        return y;
    }
};

点这里了解更多关于取值范围的文章

八数码问题

八数码难题也称九宫问题,它是在3×3的方格棋盘上,分别放置了表有数字1、2、3、4、5、6、7、8的八张牌。通过空格来移动八张牌使得棋盘由初始状态到达目标状态。

移动规则为:每次只能将与空格(上下左右)相邻的一个数字平移到空格中。

例如:

初始状态:

123
456
78

目标状态:

123
456
78

则初始状态通过将空格向左移动一次即可得到目标状态,即找到从初始状态到目标状态的解路径。

BFS算法

以下来自360百科

BFS,其英文全称是Breadth First Search。

BFS并不使用经验法则算法。从算法的观点,所有因为展开节点而得到的子节点都会被加进一个先进先出的队列中。一般的实验里,其邻居节点尚未被检验过的节点会被放置在一个被称为 open 的容器中(例如队列或是链表),而被检验过的节点则被放置在被称为 closed 的容器中。(open-closed表)

已知图G=(V,E)和一个源顶点s,宽度优先搜索以一种系统的方式探寻G的边,从而“发现”s所能到达的所有顶点,并计算s到所有这些顶点的距离(最少边数),该算法同时能生成一棵根为s且包括所有可达顶点的宽度优先树。对从s可达的任意顶点v,宽度优先树中从s到v的路径对应于图G中从s到v的最短路径,即包含最小边数的路径。该算法对有向图和无向图同样适用。

之所以称之为宽度优先算法,是因为算法自始至终一直通过已找到和未找到顶点之间的边界向外扩展,就是说,算法首先搜索和s距离为k的所有顶点,然后再去搜索和S距离为k+l的其他顶点。

算法在八数码问题中的理解

  1. 将初始状态放入队列。
  2. 若队列为空,退出。
  3. 从队列头取一个结点,按照向上、向左、向右和向下的顺序,检查移动空格后是否可以产生新的状态nst。
  4. 如果移动空格后有新状态(即移动空格之后产生的状态)产生,则检查新状态nst是否已在队列中出现过,是则放弃,返回2。
  5. 如果新状态nst未在队列中出现过,就将它加入队列,再检查新状态是否目标状态,如果是,则找到解,搜索结束;否则返回2。

实现代码

void BFS(const node & start , const node & target )
{
	int k, t, i;
	node cur, nst;   
	for(k=0; k<MAXN; ++k) 
	visited[k] = 0;  // visited[i]=1表示状态i被访问过;为0,表示未被访问
 	k = hash(start.board);
   	t = hash(target.board);
   	parent[k] = -1;  // parent[i]=k 表示状态结点i是由结点k扩展来的
   	visited[k] = 1;  
   	queue <node> que; 
   	que.push(start);  
   	while(!que.empty())
   	{
       	cur = que.front();  
       	que.pop();     
       	for(i=0; i<4; ++i)
        {    
          	if(!(i==0 && cur.space<3 || i==1 && cur.space%3==0 || i==2 && cur.space%3==2 ||i==3 && cur.space>5))
            {  
              	nst = cur;          
              	nst.space = cur.space-5+2*(i+1);      
              	nst.board[cur.space]=nst.board[nst.space];
              	nst.board[nst.space]=9;
              	k = hash(nst.board);   
              	if(visited[k] != 1) //检查新状态nst是否已在队列中出现过
				{   
                	move[k] = i;      
                	visited[k] = 1;       
                	parent[k] = hash(cur.board);         
                	if(k == t)  //目标结点hash值为t    
                   	return;           
                	que.push(nst);             
                }          
            }  
        } 
   	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值