JAVA程序设计:赛车(LeetCode:818)

你的赛车起始停留在位置 0,速度为 +1,正行驶在一个无限长的数轴上。(车也可以向负数方向行驶。)

你的车会根据一系列由 A(加速)和 R(倒车)组成的指令进行自动驾驶 。

当车得到指令 "A" 时, 将会做出以下操作: position += speed, speed *= 2。

当车得到指令 "R" 时, 将会做出以下操作:如果当前速度是正数,则将车速调整为 speed = -1 ;否则将车速调整为 speed = 1。  (当前所处位置不变。)

例如,当得到一系列指令 "AAR" 后, 你的车将会走过位置 0->1->3->3,并且速度变化为 1->2->4->-1。

现在给定一个目标位置,请给出能够到达目标位置的最短指令列表的长度。

示例 1:
输入: 
target = 3
输出: 2
解释: 
最短指令列表为 "AA"
位置变化为 0->1->3
示例 2:
输入: 
target = 6
输出: 5
解释: 
最短指令列表为 "AAARA"
位置变化为 0->1->3->7->7->6
说明:

1 <= target(目标位置) <= 10000。

官方题解中的方法二和我的方法类似,这里放出另一种方法(最短路)的代码。

class Solution {
	
	class node{
		int step,target;
		public node(int step,int target) {
			this.step=step;
			this.target=target;
		}
	}
	
    public int racecar(int target) {
    	
    	int K=33-Integer.numberOfLeadingZeros(target-1);
    	int barrier=1<<K;
    	int[] dis=new int[2*barrier+1];
    	Arrays.fill(dis, Integer.MAX_VALUE);
    	
    	dis[target]=0;
    	
    	PriorityQueue<node> q=new PriorityQueue<node>((a,b)->a.step-b.step);
    	
    	q.add(new node(0,target));
    	
    	while(!q.isEmpty()) {
    		node now=q.poll();
    		int steps=now.step;
    		int tar1=now.target;
    		if(dis[Math.floorMod(tar1, dis.length)]>steps)
    			continue;
    		
    		for(int k=0;k<=K;k++) {
    			int walk=(1<<k)-1;
    			int tar2=walk-tar1;
    			int steps2=steps+k+(tar2!=0?1:0);
    			
    			if(Math.abs(tar2)<=barrier && steps2<dis[Math.floorMod(tar2, dis.length)]) {
    				q.add(new node(steps2,tar2));
    				dis[Math.floorMod(tar2, dis.length)]=steps2;
    			}
    		}
    	}
    	
    	return dis[0];
    }
}

方法二:动态规划

class Solution {
    public int racecar(int target) {
    	
    	int[] dp=new int[target+3];
    	Arrays.fill(dp, Integer.MAX_VALUE);
    	
    	dp[0]=0; dp[1]=1; dp[2]=4;
    	
    	for(int t=3;t<=target;t++) {
    		//从最高位不为0的位算起,二进制表示的位数
    		int k=32-Integer.numberOfLeadingZeros(t);
    		if(t==(1<<k)-1) {
    			dp[t]=k;
    			continue;
    		}
    		for(int j=0;j<k-1;j++)
    			dp[t]=Math.min(dp[t], dp[t-(1<<(k-1))+(1<<j)]+k-1+j+2);
    		if((1<<k)-1-t<t)
    			dp[t]=Math.min(dp[t], dp[(1<<k)-1-t]+k+1);
    	}
    	
    	return dp[target];
    }
}

 

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值