笔试编程题

另类加法 🔗

思路:不能使用算术运算符那就只能用位运算符

        二进制加法的逻辑如下

1.上下不同,一个0一个1,结果为0+1=1,异或运算可以满足

2.上下同为0, 结果为0, 异或也运算可以满足

3.上下同为1, 若还是使用异或, 结果变成0,与期望不相符合, 想办法弥补了这点就好了. 研究发现, 1+1的结果应该是10,相当于按位与后左移一位

综上,x+y可以通过x^y + (x&y)<<1实现, 这中间的+就递归实现

    public int addAB(int A, int B) {
        if (A == 0) {
            return B;
        } else if (B == 0) {
            return A;
        } else {
            return addAB(A^B, (A&B) << 1);
        }
    }

走方格的方案数 🔗

递归法思路:

        把每个点都当作是一个出发点, 若该点坐标为(m,n), 该点出发的方案数是(m-1,n)的方案数和(m,n-1)的方案数的和. 

        递归终止条件是,当m或者n走到头了,就只有一个方向可以走, 相当于只有一种方案了, 返回1.

    public static int getPlans (int m, int n) {
        if (m == 0 || n == 0) {
            return 1;
        }
        return getPlans(m - 1, n) + getPlans(m, n - 1);
    }

最近公共祖先 🔗

 自下而上思路:

自下而上找, 不断向上找父节点, 相等即返回

    public static int getLCA (int a, int b) {
        while (a != b) {
            while (a < b) {
                b /= 2;
            }
            while (a > b) {
                a /= 2;
            }
        }
        return a;
    }

自上而下思路: 

只由编号定义的二叉树, 只能从编号的大小关系上去研究.

首先我们先把每种情况都列举出来:

1.子树在根结点的两边;

2.子树在根结点的左边;

3.子树在根结点的右边;

4.其中一个子树是根结点;

判断逻辑:

1.其中一个子树是根结点:返回根结点编号

2.子树在根结点左右两边:返回根结点编号

3.子树在根结点同侧:进入下一次递归.

import java.util.*;

public class LCA {
    public int getLCA(int a, int b) {
        return getLCA(1, a, b);
    }

    public static int getLCA (int root, int a, int b) {
        if (root == a|| root == b) {
            return root;
        }

        //获取a在左边还是右边 
        int edge = root * 2 + 2;
        int aLevel = 2;
        while (edge < a) {
            edge = edge * 2;
            aLevel++;
        } //循环结束后a < edge
        boolean aAtRight = false;
        if (a > edge - aLevel) {
            aAtRight = true;
        }

        //获取b在左边还是右边
        edge = root * 2 + 2;
        int bLevel = 2;
        while (edge < b) {
            edge = edge * 2;
            bLevel++;
        } //循环结束后a < edge
        boolean bAtRight = false;
        if (b > edge - bLevel) {
            bAtRight = true;
        }

        //a b在异侧, 返回root
        if (bAtRight && !aAtRight || !bAtRight && aAtRight) {
            return root;
        } else if (bAtRight && aAtRight) {
            if (aLevel < bLevel) {
                return a;
            } else if (aLevel > bLevel) {
                return b;
            } else {
                return getLCA(root * 2 + 1, a, b);
            }
        } else {
            if (aLevel < bLevel) {
                return a;
            } else if (aLevel > bLevel) {
                return b;
            } else {
                return getLCA(root * 2, a, b);
            }
        }

    }
}

        这个代码的问题就在, 不能应对大数据的情况, 因为递归多, 且每次递归的时间复杂度也大, 会导致栈溢出.
 

查找组成一个偶数的两个最近素数 🔗

错误思路:

一个left从前找素数, 一个right从后找素数, 找到以后left和right就相加看看是否等于偶数n, 相等就记录下当前的left和right值, 然后left和right都+=2, 知道left >= right;

思路的bug: 20的最近素数组合是13和7, 但是按照上方法得到right为13时, left的值是5, 此时13+5!=20, 继续循环会使得13错过7, 最终没有正确结果.

另起思路:

将所有小于n的素数按大小存起来, 然后从遍历, 挨个相加, 这样不会错过每一个值.

幸运的袋子 🔗

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值