准备蓝桥杯之路(三) ------ 位运算的奇淫技艺2

准备蓝桥杯之路(三) ------ 位运算的奇淫技艺2

前言

  果然刚开始坚持某件事情就会有很多的阻碍扑面而来,刚从外地回到家事情实在是太多了,更别说还有各种突发情况(断水断电,害,说多了都是泪555555),不过我肯定会继续加油,坚持更新下去的。同时也希望能够帮助到有需要的同学。

  这篇文章是对上篇文章(位运算的奇淫技艺)的一个补充和总结,如果想从头开始看的,我把上篇文章的链接粘到下面,大家直接去看就好。

上篇文章链接: 准备蓝桥杯之路(二) ------ 位运算的奇淫技艺

我是跟着哔哩哔哩的一个课程进行学习的,毕竟不是原创,所以下面我附上视频链接。
视频链接: 蓝桥杯零基础入门到比赛(二)——算法很美

习题

1. 出现k次与出现1次的数

题意描述: 数组中只有一个数出现了1次 其他数都出现了k次 请找出这个出现1次的数。

解题关键: 这道题的关键还是用某种技巧把数组中出现k次的数消掉,并且保留出现1次的那个数,这样问题就迎刃而解了。

注意这样的一个现象:10个相同的10进制数进行"不进位加法"操作之后的结果是0(eg: 如果10个3正常相加结果是30,3是那个进位,所以如果不进位的话,3就会被舍去,不进位加法的结果就是0),同理,2个相同的2进制数进行"不进位加法"操作之后的结果是0,k个相同的k进制数进行"不进位加法"操作之后的结果也是0。

到此,大致思路就理清了,具体过程看下面的代码实现。注: java中Integer.toString(i, radix)方法可以将十进制数转任意进制,并返回一个String对象。

代码实现

public class question_8 {
    public static void main(String[] args){
        int[] arr = {2, 2, 2, 9, 7, 7, 7, 3, 3, 3, 6, 6, 6, 0, 0, 0};

        /**
         * 解题关键: 2个相同的2进制数做不进位加法结果为0
         *          10个相同的10进制数做不进位加法结果为0
         *          k个相同的k进制数做不进位加法结果为0
         */
        int len = arr.length; //获取数组总长度
        char[][] kRadix = new char[len][]; //创建一个二维数组用来存储对应数字的k进制表示
        int k = 3; //k表示进制数
        int maxLen = 0; // 数字k进制表示的最大字符串长度

        //将数组中的各元素转为k进制表示
        for(int i = 0; i < len; i++){
            //反转之后实现从低到高表示k进制表示是为了各个位置对齐
            kRadix[i] = new StringBuilder(Integer.toString(arr[i], k)).reverse().toString().toCharArray();
            if(kRadix[i].length > maxLen){
                maxLen = kRadix[i].length;
            }
        }

        int[] resArr = new int[maxLen];
        //实现k进制的不进位加法,并将所有数按位加起来
        for(int i = 0; i < len; i ++){
            for(int j = 0; j < maxLen; j++){
                if(j >= kRadix[i].length){
                    resArr[j] += 0;
                }else{
                    resArr[j] += (kRadix[i][j] - '0');
                }
            }
        }

        int res = 0; //计算最后的结果
        //将最后的结果从k进制表示转化位10进制表示
        for(int i = 0; i < maxLen; i++){
            res += (resArr[i] % k) * (int)(Math.pow(k, i));
        }
        System.out.println("落单的那个数是" + res);
    }
}

2. 0~1间浮点实数的二进制表示

题意描述: 给定一个介于0和1之间的实数,(如0.625),类型为double,打印它的二进制表示(0.101),如果该数字无法精确地用32位以内(小数点后32位)的二进制表示,则印"ERROR"。

解题关键: 该题没有特殊的技巧,掌握0~1间浮点实数的二进制表示和计算方法即可。

具体的计算方法不在此赘述,实在不懂的童鞋可以参考一下我在了知乎上找的这篇文章,文章链接如下:浮点数的二进制表示以及几个例子

代码实现

import java.util.Scanner;

public class question_6
{
    public static void main(String[] args)
    {
        double num = 0.625;
        StringBuilder sb = new StringBuilder("0.");
        while(num > 0){
            // num * 2 如果大于1补1,小于1补0。
            double r = num * 2;
            if(r >= 1){
                sb.append("1");
                num = r - 1;
            }else{
                sb.append("0");
                num = r;
            }
            //如果32位之内不能表示,就跳出循环,并提示ERROR。
            if(sb.length() > 34){
                System.out.println("ERROR");
                return;
            }
        }
        System.out.println(sb);
    }
}

总结

课程的位运算相关习题到这就算结束了,但是,我很清楚自己还差的很远,这只是位运算的冰封一角,还有太多的知识和技巧需要在未来的学习中掌握和积累。后续对位运算相关知识的计划就是从刷leetcode中继续学习,如果在这个过程中遇到一些妙(难)题,我肯定还是会第一时间总结和分享出来,感谢支持。

学海无涯,学路漫漫,唯有不畏前行,才能抵达自己的梦想之地!!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值