CC150小结概念与算法

几个常用算法需要注意的点:
二分:while终止条件,mid是否取两个,mid偏左还是偏右,left和right的变更条件,跳出后的验证
递归(dfs):dfs终止条件,结果存储,下一次dfs的位置以及条件限定(重要)

位操作

常用操作 与& 、或|、非~、异或^, 左移,右移。
获取,得到第i位的知否为1。置位,将第i位设置为1.清零,00010000 取反得到掩码 11101111,然后利用与操作。将最高位到i(含)清零,(1<< i) - 1,进行与操作。将i位至0位(含)清零~((1 << (i + 1)) - 1)再与
~0 表示1串1。
取出一个数的最低为1的数。 x & ~(x - 1);

5.2给定一个介于0和1之间的实数(如0.72),类型为double,打印它的二进制表示。如果无法精确地用32位以内的二进制表示,则打印“ERROR”。
    public String numTobin(double num){
        if (num >= 1 || num <= 0){
            return "ERROR";
        }
        StringBuffer sb = new StringBuffer();
        sb.append("0.");
        while(num > 0){
            num *= 2;
            if (num >= 1){
                num -= 1;
                sb.append(1);
            }else {
                sb.append(0);
            }
            if (sb.length() >= 32){
                return "ERROR";
            }
        }
        return sb.toString();
    }
5.3给定一个正整数,找出其二进制表示中1的个数相同、且大小最相近的那两个数,一个略大,一个略小。

思路:1.位操作,较大的数:注意要判断非拖尾0的存在,要将右边有1的第一个0(位置为p = C0 (拖尾0的个数)+ C1(右边1的个数))变为1,将p后面的数据全部清零,然后补上C1个1,要判断更大值是否存在。
较小的数 : 注意C1是拖尾1的个数,C0是紧邻拖尾1的左方一连串的个数,要从1变为0 的数右侧必须包含0.否则数会大。
根据位操作的简化,可以得到out of box的算法,依据之前的数。注意拖尾与非拖尾。

5.6交换某个整数的二级制表示下的奇数位和偶数位,使用指令越少越好。

思路:利用掩码提取奇数位,右移。利用掩码提取偶数位,左移。然后相或得到。
掩码的得到直接就是0xaa以及0x55

智力题

6.5有栋建筑高100层,若从N层或者更高层扔鸡蛋,鸡蛋破,若从第N层以下的楼层扔下来不会破。给两个鸡蛋,最差的情况下,扔鸡蛋的次数最小的情况下得到N

思路: 负载均衡下,要求x1 + x2 的值保持稳定,则假设从 a扔,若有一种算法保证x1多扔一次,x2就少扔一次。a + (a - 1) + (a - 2) + … + 1 = 100, a = 14.

数学与概率

生成素数的数列:埃拉托斯尼筛法,设计出一个boolean数组,从小到大划去因子出现数组中的数。
两个子函数 void cossOff(boolean[] flags, int prime),从prime * prime 开始
int getNextPrime(boolean[] flags, int prime) 找到数组长度内,大于prime的下一个值

       for(int i = 2;i < n+1;i++){    
            result1[i-1] = i;
        }
        for(int i = 2;i < n;i++){
            for(int j = i+1;j < n+1;j++){
                if(j % i == 0)          //如果j能够整除i,使result[j-1]等于0
                    result1[j-1] = 0;
            }
        }

java类型的范围

在JAVA中一共有八种基本数据类型,他们分别是

byte、short、int、long、float、double、char、boolean
其中byte、short、int、long都是表示整数的,只不过他们的取值范围不一样
byte的取值范围为-128~127,占用1个字节(-2的7次方到2的7次方-1)
short的取值范围为-32768~32767,占用2个字节(-2的15次方到2的15次方-1)
int的取值范围为(-2147483648~2147483647),占用4个字节(-2的31次方到2的31次方-1) +-21亿的数据量,一般可以满足需求
long的取值范围为(-9223372036854774808~9223372036854774807),占用8个字节(-2的63次方到2的63次方-1)
在通常情况下,如果JAVA中出现了一个整数数字比如35,那么这个数字就是int型的,如果我们希望它是byte型的,可以在数据后加上大写的 B:35B,表示它是byte型的,同样的35S表示short型,35L表示long型的,表示int我们可以什么都不用加,但是如果要表示long型的,就一定要在数据后面加“L”。
float和double是表示浮点型的数据类型,他们之间的区别在于他们的精确度不同
float 3.402823e+38 ~ 1.401298e-45(e+38表示是乘以10的38次方,同样,e-45表示乘以10的负45次方)占用4个字节
double 1.797693e+308~ 4.9000000e-324 占用8个字节
double型比float型存储范围更大,精度更高,所以通常的浮点型的数据在不声明的情况下都是double型的,如果要表示一个数据是float型的,可以在数据后面加上“F”。

7.4实现整数的乘法、减法和除法操作

面试官想要找的就是这种能以逻辑思考逐步解决问题的人
显示代码的复用能力
思路:自己实现正号变负号,负号变正号的操作,加与乘法都可以处理,

public int negate(int a){
    int neg = 0;
    int d = a < 0 ? 1 : -1;
    while(a != 0){
        neg += d;
        a += d;
    }
    return neg;
}
乘法是注意判断,让小的数a迭代
7.6在二维平面上,有一些点,找出经过点数最多的那条线。

思路:两点之间确定直线,时间复杂度O(n*n),利用HashMap进行次数的存储。

7.7有些数的因子只有3、5、7,找出其中的第k个数。

思路:这个方法与素数筛选法类似,关键是要想得到,首先插入数据1,然后将3*1输入到队列3Q,5*1输入到5Q,然后将7*1输入到7Q,下一个数从这三个队列中给出来。
没有最优解原因,算法不是最简算法,部分拼写错误

也可以使用3个index的方法
public int getKNum(int k){
        if (k < 0){
            return 0;
        }
        Queue<Integer> quene3 = new LinkedList<Integer>();
        Queue<Integer> quene5 = new LinkedList<Integer>();
        Queue<Integer> quene7 = new LinkedList<Integer>();
        quene3.add(1);
        int val = 1;
        for (int i = 0; i < k; i++){
            int v3 = quene3.size() > 0 ? quene3.peek() : Integer.MAX_VALUE;
            int v5 = quene5.size() > 0 ? quene5.peek() : Integer.MAX_VALUE;
            int v7 = quene7.size() > 0 ? quene7.peek() : Integer.MAX_VALUE;
            val = (int)Math.min(v3, Math.min(v5, v7));
            if (val == v3){
                quene3.remove();
                quene3.add(3 * val);
                quene5.add(5 * val);    
            }  else if (val == v5){
                quene5.remove();
                quene5.add(5 * val);
            } else {
                quene7.remove();
            }
            quene7.add(7 * val);
        }   
        return val;
    }

面向对象设计

打造优雅,易于维护的面向对象代码。
单例模式,只构造这一个对象,访问与修改都是通过内部方法统一进行。

8.3运用面向对象原则,设计一款音乐点唱机。

处理本类问题思路: 处理不明确的地方,定义核心对象,分析对象关系,设计对象动作
系统组件:点唱机(Jukebox),CD,歌曲(Song),艺术家(Artist),播放列表(PlayList),显示屏(Display,在屏幕上显示详细信息)
动作:新建播放列表(新增、删除、随机播放)、CD选择器、歌曲选择器、将歌曲放进到播放队列、获取播放列表中的下一首;
用户:添加,删除

public class Jukebox(){
    private CDPlayer cdPlayer;
    private User user;
    private Set<CD> cdCollection;
    private SongSelector ts;
    public Jukebox(CDPlayer cdPlayer, User user, Set<CD> cdCollection, SongSelector ts){
    }
    public Song getCurrentSong(){
        return ts.getCurrentSong();
    }
    public void setUser(User u){
        this.user = u;
    }
}
public class CDPlayer{
    private Playlist p;
    private CD c;
    /*构造函数*/

    /*播放歌曲*/

    /*getter and setter */

}
Playlist类管理当前播放的歌曲和待播放的下一首歌曲。本质上是播放队列的包裹类,还提供了一些操作上更方便的方法。
public class PlayList {
    private Song song;
    private Quene<Song> quene;
    public Playlist(Song song, Quene<Song> quene){
        ````
    }
    public Song getNextSToPlay(){
        return quene.peek();
    }
    public void queneUpSong(Song s){
        quene.add(s);
    }
}
public class CD {
    /* 识别码、艺术家、歌曲等 */
}
public class Song{
    /* 识别码、CD(可能为空)
}
public class User {
    private String name;
    private long ID;
    public User getUser(){
        return this;
    }
}
8.7设计一个聊天服务器系统

系统的难点:如何确定某人在线,如何处理冲突信息,如何让服务器在任何负载下,都能应付自如,如何预防拒绝服务攻击。

8.10设计并实现一个散列表,使用链接(即链表)处理碰撞冲突。

思路:存储一个由链表组成的数组,链表元素为包含key 以及 value 的对象,防止冲突。

final 它可以修饰非抽象类、非抽象类成员方法和变量。你可能出于两种理解而需要阻止改变:设计或效率。static变量前可以有private修饰,表示这个变量可以在类的静态代码块中,或者类的其他静态成员方法中使用(当然也可以在非静态成员方法中使用–废话),但是不能在其他类中通过类名来直接引用,这一点很重要。实际上你需要搞明白,private是访问权限限定,static表示不要实例化就可以使用,这样就容易理解多了。static前面加上其它访问权限关键字的效果也以此类推。

构造函数前面不要加void
没有ac的原因 模板类没有处理好,未考虑到items[index]为null的情况

public class MyHashMap<K, V> {
    private final int MAX_SIZE = 100;
    private LinkedList<Cell<K, V>>[] items;

    public MyHashMap(){
        items = (LinkedList<Cell<K, V>>[])new LinkedList[MAX_SIZE];
    }
    public int getIndex(K k){
        return k.toString().length() % items.length;    
    }
    public void put(K k, V v){
        int index = getIndex(k);
        if (items[index] == null){
            items[index] = new LinkedList<Cell<K, V>>();
        }
        LinkedList<Cell<K, V>> temp = items[index];
        Cell data = new Cell(k, v);
        for (Cell c : temp){
            if (c.isEqual(data)){
                temp.remove(c);
            }
        }
        temp.add(data);
    }
    public V get(K key){
        int index = getIndex(key);
        if (null == items[index]){
            return null;
        }
        LinkedList<Cell<K, V>> temp = items[index];
        for (Cell c : temp){
            if (c.getKey().equals(key)){
                return (V) c.getValue();
            }
        }
        return null;
    }
}
public class Cell<K, V> {
    private K key;
    private V value;

    public  Cell(K key, V value){
        this.key = key;
        this.value = value;
    }
    public boolean isEqual(K k){
        return key.equals(k);
    }
    public boolean isEqual(Cell<K, V> c){
        return isEqual(c.getKey());
    }
    public K getKey(){
        return this.key;
    }
    public V getValue(){
        return this.value;
    }
}

递归与动态规划

递归结束条件,得到递归返回值,计算本身返回值,
动态规划有时是缓存了递归的结果的递归优化版。
能用迭代尽量不适用递归。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值