A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 刘蕴学 中级黑马   /  2012-5-17 07:12  /  4960 人查看  /  29 人回复  /   1 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 刘蕴学 于 2012-5-20 12:37 编辑

导语:表要瞧不起基础,表要攀比工具,基础无所不能!真的是酱紫吗?
我不想知道你们的基础是多么烂,请原谅我用这个词,我只想知道,你敢不敢跟着我把这些题全做下去,直到完虐入学测试的考试,嗯,就这么简单。

觉得难的请认真看老毕视频第二天13-16四节视频。

第三个,仍然是集合
这个题稍微有点简单了,主要还是灵活运用,考思维的,第二题如果你掌握了,这题不难。
按照第二题的方式实现给定集合A{0,1....172,173}用一个int表示
这个题就是2个short(byte)的事情,我的说话方式以及描述都在误导你放弃最简单的方式。当然在实际开发中,如果这个连续的集合是可以预期的,尽量采用这种方式来传输或者保存,以减小空间占用。
举个例子吧,比如说服务端给客户端传递1个帖子,是不是得有楼层编号,这里你只需要告诉客户端有帖子有多少回复就行了,而不是每个回复的数据区都写一个int来传这个回复的编号。
也许你们觉得我这是无聊,是吃饱撑的,但我要说,工作中,你的想法会很多,如果一份代码,你每天都有想法,每天都在改,或者你是个完美主义者,那么你永远无法按时完成工作,你把大部分时间都浪费在你的所谓的更好的想法上了。
工作中的要点就是第一时间写出功能,不考虑优化(除非你确认你这个优化是有效的,你很熟练可以默写),等到项目完成之后,回过头来在去检验你的那些想法,没人会花钱雇佣一个不能按时完成工作的人。

由于原来的第二题可能有点不好理解,换个试试,上过初中的看不懂的自己撞墙去
第二个,集合
1.给定集合A{0,1,2.....30,31}
2.给定集合B{5,6....10,11}
3.求 A 和 B 的交集
4.求 A 和 B 的并集
5.求 B 相对于 A 的补集
6.求 A 对 B 差集
7.求给定集合 C{7,9} 是 A 和 B 哪个集合的子集,并实现任意集合子集的查询功能
8.以上所有集合必须使用一个int表示而非数组,所有代码均以按位运算符进行
9.使用查表法可以根据int表示的集合正确输出该集合所表示的数组。
10.必须详细写出解题思路,实现方法。去工作之后,你写的代码不是给你自己看的,是给别人看的,你不写设计思路,不写注释,你让人怎么看?
答案在25楼,24楼是位运算的笔记 22,23楼的解题思路你们也可以看下,而26楼是一个简单的用户权限实现,很基础的应用,真的权限机制比这个复杂太多

第一个
用最简便的单循环输出如下,并详细写出原理以及解题思路,并说明其中问号处应该填什么?用字符串的木有小JJ,如果你真觉得等号后边的一排1没变化,那你可就错喽
本题13楼以及15楼的方式将不在有分,但是,还有另外一种方式,写的出来仍然有分。
  1. 11111111111111111111111111111110 ? 00000000000000000000000000000001 = 11111111111111111111111111111111
  2. 11111111111111111111111111111100 ? 00000000000000000000000000000011 = 11111111111111111111111111111111
  3. 11111111111111111111111111111000 ? 00000000000000000000000000000111 = 11111111111111111111111111111111
  4. 11111111111111111111111111110000 ? 00000000000000000000000000001111 = 11111111111111111111111111111111
  5. 11111111111111111111111111100000 ? 00000000000000000000000000011111 = 11111111111111111111111111111111
  6. 11111111111111111111111111000000 ? 00000000000000000000000000111111 = 11111111111111111111111111111111
  7. 11111111111111111111111110000000 ? 00000000000000000000000001111111 = 11111111111111111111111111111111
  8. 11111111111111111111111100000000 ? 00000000000000000000000011111111 = 11111111111111111111111111111111
  9. 11111111111111111111111000000000 ? 00000000000000000000000111111111 = 11111111111111111111111111111111
  10. 11111111111111111111110000000000 ? 00000000000000000000001111111111 = 11111111111111111111111111111111
  11. 11111111111111111111100000000000 ? 00000000000000000000011111111111 = 11111111111111111111111111111111
  12. 11111111111111111111000000000000 ? 00000000000000000000111111111111 = 11111111111111111111111111111111
  13. 11111111111111111110000000000000 ? 00000000000000000001111111111111 = 11111111111111111111111111111111
  14. 11111111111111111100000000000000 ? 00000000000000000011111111111111 = 11111111111111111111111111111111
  15. 11111111111111111000000000000000 ? 00000000000000000111111111111111 = 11111111111111111111111111111111
  16. 11111111111111110000000000000000 ? 00000000000000001111111111111111 = 11111111111111111111111111111111
  17. 11111111111111100000000000000000 ? 00000000000000011111111111111111 = 11111111111111111111111111111111
  18. 11111111111111000000000000000000 ? 00000000000000111111111111111111 = 11111111111111111111111111111111
  19. 11111111111110000000000000000000 ? 00000000000001111111111111111111 = 11111111111111111111111111111111
  20. 11111111111100000000000000000000 ? 00000000000011111111111111111111 = 11111111111111111111111111111111
  21. 11111111111000000000000000000000 ? 00000000000111111111111111111111 = 11111111111111111111111111111111
  22. 11111111110000000000000000000000 ? 00000000001111111111111111111111 = 11111111111111111111111111111111
  23. 11111111100000000000000000000000 ? 00000000011111111111111111111111 = 11111111111111111111111111111111
  24. 11111111000000000000000000000000 ? 00000000111111111111111111111111 = 11111111111111111111111111111111
  25. 11111110000000000000000000000000 ? 00000001111111111111111111111111 = 11111111111111111111111111111111
  26. 11111100000000000000000000000000 ? 00000011111111111111111111111111 = 11111111111111111111111111111111
  27. 11111000000000000000000000000000 ? 00000111111111111111111111111111 = 11111111111111111111111111111111
  28. 11110000000000000000000000000000 ? 00001111111111111111111111111111 = 11111111111111111111111111111111
  29. 11100000000000000000000000000000 ? 00011111111111111111111111111111 = 11111111111111111111111111111111
  30. 11000000000000000000000000000000 ? 00111111111111111111111111111111 = 11111111111111111111111111111111
  31. 10000000000000000000000000000000 ? 01111111111111111111111111111111 = 11111111111111111111111111111111
复制代码
这个题的考点不在于你到底对位运算有多了解,而是位移操作你是否熟练,以上图为例,这表示了3种唯一操作符,我是拿这个图来解释3种位移操作符的区别
第一列为左移,第二列为无符号右移,第三列为有符号位移,但单拿解题来说,前俩个操作求第三列也可以,恒值也可以,但主要是3列之间的关系。
如果你把第0行打印出来的话,第一行是第一列表示负数最大值,第一行第二列0表示正数最小值,这么是因为0算在正数里,区分为最高位的符号位
而第31行第一列为int的最小值,第二列为int最大值。而第二列的数其实也是2 4 8 16 32 64 128...进制的最大值。
第一列和第二列存在互补关系,也就是说通过~x可以拿到另外一列。
我着重强调好几次,要找规律,规律不就是位移么,你们都是第一列到第二列怎么来的,为什么不考虑怎么从第三列演变成第一列和第二列?
另外虽然第三列一直是-1,但我也说他不是静止的,难道你们都没发现规律?

而问号处,其实可以放4种,+ ^ | ~(但这个~有点限制),但要考虑为什么会这样子,为什么&不行。这有助于分析什么情况下更适合用什么运算符。

本题的这张图,我不知道你们有没有仔细考虑过,像不像一些网站的相册上切换照片时的特效剪切?第一列从上往下,第二列从下往上?而本题由于是位运算,并且运算方面效率不错,再加上可以指定任意行,所以用来处理图像剪切的特效时是很有用处的。这个大家可以试验下,每次32行,逐行取,并把该剪切窗格布满整个图像,下方放上下一张图片,然后用setclip根据每一行的数字来切窗口,最后只完整的显示下一张图。当然这种方法并不是很好,但你应该试着尝试把所学到的知识加以利用。
  1.   //这个足够看出来3种位移方式的区别了
  2.                 //至于?的运算符,+ ^ |三种都行
  3.                 for (int shift = 1; shift < Integer.SIZE; shift++)
  4.         {
  5.                         System.out.print(getIntegerToBinary(-1 << shift));
  6.                         System.out.print(" ? " + getIntegerToBinary(-1 >>> Integer.SIZE - shift));
  7.                         System.out.println(" = " +getIntegerToBinary(-1 >> shift));
  8.                
  9.         }
复制代码
这里边的 getIntegerToBinary  方法我在第五题的答案里已经写过了,就不在这发占篇幅了。这里有个小知识点,是第五题没有说的,-1 变31  -2变30,用32加上去就行,但局限性很大,不支持32+以后的情况。
  1. for (int shift = 1; shift < Integer.SIZE; shift++)
  2.         {
  3.                         System.out.print(getIntegerToBinary(-1 << shift));
  4.                         System.out.print(" ? " + getIntegerToBinary(-1 >>> shift));
  5.                         System.out.println(" = " +getIntegerToBinary(-1 >> shift));
  6.                
  7.         }
复制代码
对比下两个变形,如果根据这个代码的图,第二列不变,而改动第一列应该怎么办?

评分

参与人数 2黑马币 +60 收起 理由
kevindavid + 30 赞一个!
贠(yun)靖 + 30 给你点钱吧 生的没钱置顶了

查看全部评分

29 个回复

倒序浏览
本帖最后由 谢述华 于 2012-5-17 10:07 编辑

第一题答案(还有点不完美。。。修改下再添加上思考步骤什么的~~)

public class AbsDem{
   public static void main(String[] args1) {
   for(int i=-2;i>-2147483648;i=2*i)
   {
    int j=-(i+1);
   
    System.out.println(Integer.toBinaryString(i)+" + "+Integer.toBinaryString(j)+"="+Integer.toBinaryString(-1));
    }
   System.out.println(Integer.toBinaryString(-2147483648)+" + "+Integer.toBinaryString(2147483647)+"="+Integer.toBinaryString(-1));
   }
   
}

点评

呵呵,你没抓规律,仔细看下图  发表于 2012-5-17 10:03
回复 使用道具 举报
本帖最后由 王永旺 于 2012-5-17 13:06 编辑

中间的符号使用异或‘^’还有按位或‘|’符号均可。
我的思路是首先确定需要两个变量,然后通过观察我发现只要两个变量同一位不同则为1,所以 应该用异或 ‘^’
但我同时发现这个表达式同时满足按位"或"的结果,所以这里使用'|',‘^’两个个符号均能得到正确结果。
  1. public class Num {
  2.         public static void main(String[] args) {
  3.                 int a  = -1;
  4.                 int b  = 0;
  5.                 String s = "00000000000000000000000000000000";
  6.                 for (int i = 1; i < 32; i++) {        
  7.                         a=a<<1;
  8.                         b=1+(b<<1);        
  9.                         System.out.println(Integer.toBinaryString(a)+"  ^  "         
  10.                                                +s.substring(i)+Integer.toBinaryString(b)
  11.                                                +" = "+Integer.toBinaryString(a^b));         //这里使用a^b   a|b  均能得到正确结果。

  12.                 }        
  13.         }        
  14. }
复制代码

点评

老王你被坑拉,哈哈哈,这个题有规律滴  发表于 2012-5-17 10:13

评分

参与人数 1技术分 +1 收起 理由
贠(yun)靖 + 1

查看全部评分

回复 使用道具 举报
谢述华 发表于 2012-5-17 09:34
第一题答案(还有点不完美。。。修改下再添加上思考步骤什么的~~)

public class AbsDem{

是的,少几个零。。。

点评

我说的规律不是0啊  发表于 2012-5-17 10:16
回复 使用道具 举报
是加法运算= =!第一个数加第二个数 等于第三个 然后只保留4个8位

点评

加法是没错吗,可以,问题是为什么要强调保留4个8位?  发表于 2012-5-17 10:25
回复 使用道具 举报
老王的我认为完全符合要求啊,我的就不修改了,是我的真实水平。。。

点评

尝试下嘛,呵呵  发表于 2012-5-17 14:27
第一个要摸规律,摸不到规律就白撤,而且等号后边的一排1不是不变的,只能提示这么多了,其实代码自己敲出来跟看完全是两码事  发表于 2012-5-17 10:32
回复 使用道具 举报
本帖最后由 王永旺 于 2012-5-17 11:01 编辑

搞错了

点评

错了你也发,小心关小黑屋  发表于 2012-5-17 15:10
回复 使用道具 举报
本帖最后由 黄奕豪 于 2012-5-17 14:48 编辑
  1. <p>class Demo
  2. {
  3. public static void main(String[] args)
  4. {
  5.   Run r=new Run();
  6.   r.print1();
  7. }
  8. }</p><p>class Run
  9. {
  10. int head=-2;//第一个数据
  11. int end=0;//第二个数据
  12. void print1()
  13. {
  14.   for (int i=0;i<31 ;i++ )
  15.   {
  16.    end=(end<<1)+1;
  17.    String str="";
  18.    //第二个数据补足32位循环
  19.    for(int j=0x80000000;j!=0;j>>>=1)
  20.    {
  21.     str+=(end&j)==0?'0':'1';
  22.    }
  23.    //单循环输出
  24.    System.out.println(Integer.toBinaryString(head<<i)+"^"+str+"="+Integer.toBinaryString(head<<i^end));
  25.   }
  26. }
  27. }</p>
复制代码
?可以用^表示,代码如下,可是就是不知道怎么把正数的前面0补足!先上代码

在网上查了一下,加上第二个数补足32位的完整程序,不知道符不符合要求?

点评

太复杂了亲  发表于 2012-5-17 14:27
回复 使用道具 举报
李月 中级黑马 2012-5-17 12:48:52
9#
public class yiwei {

        /**
         * @param args
         */
        public static void main(String[] args) {
                // TODO Auto-generated method stub
               
                //System.out.print(Integer.toBinaryString(32766));
                int x=1;
                int i=2147483646;
                String s="0000000000000000000000000000000";
                for(int n=30;n>=0;n--)
                {
                        System.out.print(Integer.toBinaryString(i)+"|"+s.substring(0,n+1)+Integer.toBinaryString(x)+"=");
                       
                       
                        System.out.println(Integer.toBinaryString(i|x));
                       
                        i=i<<1;
                        x=x<<1|1;
                       
                               
                }
        }

}
回复 使用道具 举报
徐然 黑马帝 2012-5-17 12:59:49
10#
  public static void main(String[] args)
        {
               
                        //System.out.println(Integer.toBinaryString(Integer.MAX_VALUE));
                                for(long x=-2,y=1;x>=-2147483648 & y<=2147483647;x=x*2,y=y*2+1)
                                {
                                        long z = x + y;
                                        System.out.println(Integer.toBinaryString((int)(x))+"+"+Integer.toBinaryString((int)(y))+"="+Integer.toBinaryString((int)(z)));
                                       
                                       
                                }


        }

点评

你这还真不是正解亲~~  发表于 2012-5-17 13:11
回复 使用道具 举报
徐然 黑马帝 2012-5-17 13:01:14
11#
本帖最后由 徐然 于 2012-5-17 13:03 编辑

都被楼主带坑里了吧,其实很简单,我这就是正解
这题就考一点,类型转换

点评

骚年,不要自信满满,须知人外有人,天外有天,墙外有红杏。。。  发表于 2012-5-17 13:10
回复 使用道具 举报
public class yiwei {

        /**
         * @param args
         */
        public static void main(String[] args) {
                // TODO Auto-generated method stub
               
               
                int x=1;
                int i=-1;
                String s="0000000000000000000000000000000";
                for(int n=30;n>=0;n--)
                {
                        i=i<<1;
                        System.out.print(Integer.toBinaryString(i)+"|"+s.substring(0,n+1)+Integer.toBinaryString(x)+"=");
                       
                       
                        System.out.println(Integer.toBinaryString(i|x));
                       
                       
                        x=x<<1|1;
                       
                               
                }
               
        }

}

我又改了,这回不少个1了。

点评

差一点点  发表于 2012-5-17 14:20

评分

参与人数 1技术分 +1 收起 理由
贠(yun)靖 + 1

查看全部评分

回复 使用道具 举报
话说只能搞成这样了
  1. public class NUM {
  2.         public static void main(String[] args) {        
  3.                
  4.                 int a =-1;
  5.                 String s= "00000000000000000000000000000000" ;
  6.                 for (int i =1;i<32; i++) {        
  7.                         a=a<<1;
  8.                         System.out.println(Integer.toBinaryString(a)+" ^ "
  9.                                                +s.substring(i)+Integer.toBinaryString(~a)+" = "
  10.                                                +Integer.toBinaryString(a+~a));
  11.                 }        
  12.         }        
  13. }
复制代码

点评

ok,你这个完全没有问题,也对,走的是另外一条路  发表于 2012-5-17 13:33

评分

参与人数 1技术分 +1 收起 理由
贠(yun)靖 + 1 再给你一分,这个比那个好多了~~.

查看全部评分

回复 使用道具 举报
徐然 黑马帝 2012-5-17 13:24:47
14#
徐然 发表于 2012-5-17 13:01
都被楼主带坑里了吧,其实很简单,我这就是正解
这题就考一点,类型转换 ...

额~~表打击我撒~~~我在论坛一直是被打击对象,虽然没人认识我,但是看大家的问题和回答我就倍受打击了
好不容易有次独立思考的机会,额~~~算了我还是回家种地把

点评

额,其实也没啥,多练练就好了  发表于 2012-5-17 14:20
回复 使用道具 举报
public class Demo {
        public static void main(String[] args) {
                int i=-1;
                StringBuilder ling=new StringBuilder("0000000000000000000000000000000");
                for(int row=1;row<=31;row++){
                        i=i<<1;
                        int sum=i|~i;
                        System.out.println(Integer.toBinaryString(i)+
                                        "?"+ling+Integer.toBinaryString(~i)+"="+
                                        Integer.toBinaryString(sum));
                        ling.deleteCharAt(0);
                }
        }
}

点评

不过你这个循环减0的StringBuilder的用法确实是亮点  发表于 2012-5-17 14:22
我了个去,deleteCharAt都出来了。。。。  发表于 2012-5-17 14:19

评分

参与人数 1技术分 +2 收起 理由
贠(yun)靖 + 2 这个好,避免内存泄露了都~~~

查看全部评分

回复 使用道具 举报
我确实想不出该怎么用不用字符串把头前的0打出来。。既然要用字符串 还是StringBuilder的deleteCharAt()方法效率高点  还忘你指点下怎么不用字符串把头前的0打印出来  难道搞一个函数打印一个0  调用这个函数(31-row)次?

点评

代码重用上方便点,其实你写"xxx"+"???"这样的也是一样的,编译时会自动优化成Stringbuilder来处理  发表于 2012-5-17 14:49
单拿这个题来说你这个做法没什么问题,不过一般都是用通用的补全方法,就是subString一排0的字符串,截断的长度是32-integer.tobinaryString的长度、  发表于 2012-5-17 14:48
回复 使用道具 举报
本帖最后由 黄奕豪 于 2012-5-17 14:49 编辑
黄奕豪 发表于 2012-5-17 12:39
?可以用^表示,代码如下,可是就是不知道怎么把正数的前面0补足!先上代码

在网上查了一下,加上第二个数 ...

:L我只学到了毕老师Java基础的第十天,也只能用最土的方法写出来了!!具体算法是,第一个数据循环每次向左移计数器i位(head<<i),第二个数据每次向左移一位然后加上1再赋值回给原数据(end=(end<<1)+1)得到进入后面异或的第二个数字,然后利用最后得到的两个数字异或得到最后一个数字!!是我的代码阅读性太差了!!555555

点评

多动动脑筋,实现上并不复杂,就看你能不能想到  发表于 2012-5-17 15:07
其实我的做法,简单到。。。第二天足以  发表于 2012-5-17 15:02
回复 使用道具 举报
徐然 黑马帝 2012-5-17 15:35:34
18#
这样行不,求详解

class Test
{
        public static void main(String[] args)
    {
                String s = "00000000000000000000000000000000";
                int count = 1;
        for(long x=-2;x>=-2147483648;)
        {               
            System.out.println(Integer.toBinaryString((int)(x))+"+"+
                                                    s.substring(count)+Integer.toBinaryString((int)(~x))+"="+
                                                    Integer.toBinaryString((int)(~x+x)));
                     x=x*2 ;
                     count++;            
        }
    }
}

评分

参与人数 1技术分 +1 收起 理由
贠(yun)靖 + 1 可以的

查看全部评分

回复 使用道具 举报
本帖最后由 高云飞 于 2012-5-17 17:08 编辑

                int a = 1;
                int b = ~a;
                StringBuffer zeros = new StringBuffer ("00000000000000000000000000000000");
                for (int i = 0; i < 31; i++) {
                        System.out.println(Integer.toBinaryString(b) + "^" + zeros.substring(i+1) +  Integer.toBinaryString(a) + "=" + Integer.toBinaryString(a^b));
                        b = b << 1;
                        a = (a << 1) + 1;
                }
终于用这种方式实现格式与题目一致了,本来想用格式控制字符串的,发现,实现起来太难了,没有实现的了。就用这种方法了。
回复 使用道具 举报
class Lesson3
{
        public static void main(String []args)
        {
                int x=-1;
                int y=31;
                for (int i=1;i<32 ;i++ )
                {
                        int a=x<<i;
               
                        int b=-1^a;
                        x=-1;
                        int sum=a|b;
                       
                        String s="00000000000000000000000000000000";
                       
                        System.out.println(Integer.toBinaryString(a)+"|"+s.substring(0,y--)+Integer.toBinaryString(b)+"="+Integer.toBinaryString(sum));
                       
                }
        }       
       
       
       
}
回复 使用道具 举报
12下一页
您需要登录后才可以回帖 登录 | 加入黑马