算法题积累 切面条

一、切面条

一根高筋拉面,中间切一刀,可以得到2根面条。
如果先对折1次,中间切一刀,可以得到3根面条。
如果连续对折2次,中间切一刀,可以得到5根面条。
那么,连续对折10次,中间切一刀,会得到多少面条呢?

/**
     * 思路一:算弯道
     * 不折    直线2   折点为0
     * 折一次  直线2   折点为1(2^0)
     * 折两次  直线2   折点为3(2^0+2^1)
     * 折三次  直线2   折点为7(2^0+2^1+2^2)
     * 折四次  直线2   折点为15(2^0+2^1+2^2+2^3)
     * ……
     * 折N次  直线2   折点为2^N-1(2^0+2^1+2^2+2^3+……+2^(N-1))
     * 
     * --------------------------
     * 一个折点代表一条线  总条数=直线+折点
     */
    private double t1(int a) {
        double s = 2;
        if (a==0) return s;
        s = Math.pow(s,a-1) + t1(a-1);
        return s;
    }
/**
     * 思路二:每一次折至少有一个折点,这个折点在每次折的时候都不会翻倍,所以下一次折的条数是2*(上一次折的条数-1)+1(不会翻倍的折点)
     * 不折    2
     * 折一次  3 2*(2-1)+1
     * 折两次  5 2*(3-1)+1
     * 折三次  9 2*(5-1)+1
     * 折四次  17 2*(9-1)+1
     * ……
     * 折N次  2(N-1)+1
     *
     * --------------------------
     * 一个折点代表一条线  总条数=直线+折点
     */
    private double t2(int a) {
        int sum = 2;
        for (int i = 1; i <= a; i++) {
            sum = (sum-1)*2+1;
            // sum = sum*2-1
        }
        return sum;
    }

二、数字中有两个数出现奇数次,其余数出现偶数次,分别求出这两个值?

假设两个出现奇数次的数为a、b,现将所有数异或,结果必然为a^b,如果此时a^b!=0,则必定在二进制数字某个位置存在1,这表明a和b在该位上不相等,根据这个条件,将该位上为1和为0的分别取出与a^b与,结果便可算出。

public class Xor extends GetTwoValues{

    public void getTwoValuesByXor(int[] arr) {
        GetTwoValues getTwoValues = new GetTwoValues() {
            /**
             * 通过异或获取数组中出现奇数次的两个数
             *
             * @param arr
             * @date 2022/5/30 11:00
             */
            @Override
            public void getTwoOddOccurrenceValuesFromAnArrayByXor(int[] arr) {
                int a = 0, b, eor = 0;
                // 获取a^b
                for (int i : arr) {
                    eor ^= i;
                }
                /** 获取a^b最右边为1的值
                 * a         1100
                 * b         1011
                 * eor       0111
                 * ~eor      1000
                 * ~eor + 1  1001
                 * rightOne  0001
                 */
                int rightOne = eor & (~eor + 1);
                for (int i : arr) {
                	// 与rightOne &后为0,表示该位置为0(xxx0)
                    if ((rightOne & i) == 0) {
                    	// 所有xxx0类型的值异或或,获得第一个值
                        a ^= i;
                    }
                }
                // b = a ^ b ^ a;
                b = eor ^ a;
                System.out.println("a = " + a + "; b = " + b);
            }
        };
        getTwoValues.getTwoOddOccurrenceValuesFromAnArrayByXor(arr);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蓝桉未与

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值