另类加法
请编写一个函数,将两个数字相加。不得使用+或其他算数运算符。
给定两个int A和B。请返回A+B的值
解题思路:
使用位运算来代替加法
异或(相异为1,相同为0) A与B做异或
假设A的二进制位为0011,B的二进制位为0101
那么A^B = 0110 即相当于A+B不算进位的和。
与(有0位0) A与B做与运算
假设A的二进制位为0011,B的二进制位为0101
那么A&B = 0001 即相当于进位
那么此时A+B = A^B+(A&B)<<1
由于不能有加法,所以当(A&B)<<1 等于0的A+B的和就可以得出了。
递归:
import java.util.*;
public class UnusualAdd {
public int addAB(int A, int B) {
if(B == 0){return A^B;}
return addAB(A^B,(A&B)<<1);
}
}
非递归
import java.util.*;
public class UnusualAdd {
public int addAB(int A, int B) {
int sum =0;
int jin = 0;
while(B!=0){
sum = A^B;
jin = (A&B) << 1;
A = sum;
B = jin;
}
return A^B;
}
}
饥饿的小易
算法链接
小易总是感觉饥饿,所以作为章鱼的小易经常出去寻找贝壳吃。最开始小易在一个初始位置x_0。对于小易所处的当前位置x,他只能通过神秘的力量移动到 4 * x + 3或者8 * x + 7。因为使用神秘力量要耗费太多体力,所以它只能使用神秘力量最多100,000次。贝壳总生长在能被1,000,000,007整除的位置(比如:位置0,位置1,000,000,007,位置2,000,000,014等)。小易需要你帮忙计算最少需要使用多少次神秘力量就能吃到贝壳。
输入描述:
输入一个初始位置x_0,范围在1到1,000,000,006
输出描述:
输出小易最少需要使用神秘力量的次数,如果使用次数使用完还没找到贝壳,则输出-1
思路:
用一个哈希表存储已经遍历过的点,避免重复
使用队列记录还未访问过的结点
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
long x = sc.nextLong();
System.out.println(bfs(x));
}
}
private static int bfs(long x){
//存放未访问的点
Queue<Long> queue = new LinkedList<>();
//存放已经保存的点 Long代表值 Integer代表的是次数
Map<Long,Integer> map = new HashMap<>();
map.put(x,0);
queue.add(x);
while(!queue.isEmpty()){
//队列中元素出队列,此时判断这个元素是否满足条件
long count = queue.poll();
//取得次数
int cnt = map.get(count);
if(count == 0){
return cnt;
}
if(cnt > 100000){
continue;
}
//判断4x+3 和 8x+7有没有被访问,若没有就入对列
long nx =(4*count+3)%1000000007;
if(map.get(nx) == null){
map.put(nx,cnt+1);
queue.add(nx);
}
nx = (8*count+7)%1000000007;
if(map.get(nx) == null){
map.put(nx,cnt+1);
queue.add(nx);
}
}
return -1;
}
}