编程之美

《编程之美》中的一道错题 4.1 金刚坐飞机

断了今生、忘了曾经 提交于 2020-03-27 04:32:09
4.1 金刚坐飞机问题 话说,这道题的解法和答案都是有问题的,我们只看原题: 现在有一班飞机将要起飞,乘客们正准备按机票号码( 1, 2, 3, … N )依次排队登机。突然来了一只大猩猩(对,他叫金刚)。他也有飞机票,但是他插队第一个登上了飞机,然后随意地选了一个座位坐下了 。根据社会的和谐程度,其他的乘客有两种反应: 1. 乘客们都义愤填膺,“既然金刚同志不遵守规定,为什么我要遵守?”他们也随意地找位置坐下,并且坚决不让座给其他乘客。 2. 乘客们虽然感到愤怒,但还是以“和谐”为重,如果自己的位置没有被占领,就赶紧坐下,如果自己的位置已经被别人(或者金刚同志)占了,就随机地选择另一个位置坐下,并开始闭目养神,不再挪动位置。 那么,在这两种情况下,第 i 个乘客(除去金刚同志之外)坐到自己原机票位置的概率分别是多少? (一)先看第一问,我认为作者总结的公式太抽象了,至少能看懂那个公式的人不多。 遇到这样的问题,就是枚举,猜出公式,然后数学归纳法。 假设N=3,即1、2、3。 先来分析第一个人的概率: 如果金刚占了1,概率1/3,那么第1个人永远没机会坐到自己座位,概率为0。 如果金刚不占1(占了2或3)——概率2/3,这种情况下,第1个人可以在1和另一个座位(2或3)中进行选择,概率1/2,即P=2/3 * 1/2 = 1/3。 合计:1/3——这是第一个人坐到自己座位的概率。

《编程之美》读书笔记13: 4.1 金刚坐飞机问题

微笑、不失礼 提交于 2020-03-26 12:36:47
《编程之美》读书笔记13: 4.1 金刚坐飞机问题 问题: 现在有一班飞机将要起飞,乘客们正准备按机票号码( 1, 2, 3, …N)依次排队登机。突然来了一只大猩猩(对,他叫金刚)。他也有飞机票,但是他插队第一个登上了飞机,然后随意地选了一个座位坐下了1。根据社会的和谐程度,其他的乘客有两种反应: 1. 乘客们都义愤填膺,“既然金刚同志不遵守规定,为什么我要遵守?”他们也随意地找位置坐下,并且坚决不让座给其他乘客。 2. 乘客们虽然感到愤怒,但还是以“和谐”为重,如果自己的位置没有被占领,就赶紧坐下,如果自己的位置已经被别人(或者金刚同志)占了,就随机地选择另一个位置坐下,并开始闭目养神,不再挪动位置。 那么,在这两种情况下,第 i 个乘客(除去金刚同志之外)坐到自己原机票位置的概率分别是多少? 设 总座位数为n: 对问题一,每个人都是随机选择座位,任意一个人坐在指定座位的概率相同,因而第i个乘客坐在其座位的概率是 1/n。 对问题二,答案和金刚的原来座位编号有关。不妨先去除金刚的座位,将乘客(根据机票号)和剩下的座位,按原大小顺序从1开始重新编号。 用F(i,n)表示在新排列中(共有n-1个乘客座位和金刚原来的座位),新的第i个乘客坐在其原来座位的概率, 则在n个座位中: ① 金刚若挑自己的座位或选的座位在第i个座位后(共有n-i个座位满足这个条件)

【编程之美】金刚坐飞机问题

拈花ヽ惹草 提交于 2020-01-03 10:48:08
题目描述 现在有一架飞机要起飞,乘客们正准备按机票号码(1,2,3...,N)一次排队登机。突然来了一只大猩猩(金刚)。他也有机票,但是他插队第一个登上了飞机,然后随意的选择了一个座位坐下了。根据社会的和谐程度,其他的乘客有两种反应: 1.乘客们都义愤填膺,“既然金刚同志都不守规矩,为什么我要遵守?”他们也随意的找位置坐下,并且坚决不让座位给其他乘客。 2.乘客们虽然感到愤怒,但是还是以“和谐”为重,如果自己的位置没有被占领,就赶紧坐下,如果自己的位置已经被别人(或者金刚同志)占了,就随机的选择另一个位置坐下,就开始闭目养神,不在挪动。 问题:在这两种情况下,第i个乘客(出去金刚同志外)做到自己原机票位置的概率分别是多少? 问题解答 第一问 :该问题相当于排序问题,总的排序总数是n个人的全排列为N!,如果第i个人做到第i个位置上,那么其余n-1个人的全排列为(N-1)!,综上所求概率为(N-1)!/N!=1/N。 第二问 :《编程之美》讲得比较复杂,没怎么看懂,在网上找了几个博文对该问题的解答,综合一下,这样理解比较容易: 假设: F(i,n)表示在有n个座位的前提下,第i个人恰好做到第i个座位的概率; P(K=j)表示金刚刚好坐在位置j上的概率; P(i|K=j)表示在金刚做到位置j的前提下,第i个人恰好做到第i个位置上的概率。 由以上的假设根据全概率公式有:  

编程之美 - 1 的数目

我的梦境 提交于 2019-12-13 16:15:28
问题: 给定一个十进制整数N,写下从1开始到N的所有数字,然后数一下其中1的个数。 例如N = 16, 1 , 2, 3, 4, 5, 6, 7, 8, 9, 1 0, 11, 1 2, 1 3, 1 4, 1 5, 1 6 其中 1 的个数为 9 个。 分析: 第一种方式比较暴力, 一个数字一个数字的查。复杂度为 N*(log2N) 第二种方式找规律,如例子中N=16的情况来看: - 第一个是个位上的 1: 1, 11 两个 - 第二个是十位上的 1: 10, 11, 12,13,14,15,16 七个 1: 9 个 再如N = 23 - 第一个是个位上的 1: 1, 11,21 三个 - 第二个是十位上的 1: 10 ~ 19 十个 1: 13 个 所以如果 十位上递增了一个,那么个位上的1便会多加一个; 十位数决定个位数 如果十位上的数是一个1,或大于1,那么个位数有多少个,便决定十位上1的个数。 再如 N = 123 - 第一个是个位上的 1: 1, 11,21...121 0, 10 ,20, .... 120 13个 - 第二个是十位上的 1: 10 ~ 19, 110 ~ 119 20个 - 第三个是百位上的 1: 100 ~ 123, 24个 1:13 + 20 + 24= 57 按照位数分析,每位上的1和它的高位和低位都有关系。 假设当前位 : c 高位: h

图书-软件:《编程之美》

拥有回忆 提交于 2019-12-03 08:03:52
ylbtech-图书-软件: 《编程之美》 《编程之美》是2008年 电子工业出版社 出版的图书,作者是《编程之美》小组。 1. 返回顶部 1、 书 名:编程之美 又 名:编程之美——微软技术面试心得 作 者:《编程之美》小组 ISBN:9787121060748 定 价:40 出版社:电子工业出版社 出版时间:2008 装 帧:平装 开 本:16 目录 1 内容简介 2 作品目录 3 作品评价 4 作者简介 2、 2. 返回顶部 1、 内容简介 该书收集了 约60道算法和程序设计题目 ,这些题目大部分在近年的笔试,面试中出现过,或者是被微软员工热烈讨论过。作者试图从书中各种有趣的问题出发,引导读者 发现问题,分析问题,解决问题,寻找更优的解法 。 本书的内容分为下面几个部分: 游戏之乐:从游戏和其他有趣问题出发,化繁为简,分析总结。 数字之魅 :编程的过程实际上就是和数字及字符打交道的过程。这一部分收集了一些好玩的对数字进行处理的题目。 结构之法:汇集了常见的对字符串、链表、队列,以及树等进行操作的题目。 数学之趣:列举了一些不需要写具体程序的数学问题,锻炼读者的抽象思维能力。 书中绝大部分题目都提供了详细的解说。 每道题目后面还有一至两道扩展问题,供读者进一步钻研。 书中还讲述了面试的各种小故事,告诉读者微软需要什么样的技术人才,重视什么样的能力,如何甄别人才

java并发编程之美-阅读记录7

孤街浪徒 提交于 2019-11-27 03:49:14
java并发包中的并发队列 7.1ConcurrentLinkedQueue   线程安全的无界非阻塞队列(非阻塞队列使用CAS非阻塞算法实现),其底层数组使用单向列表实现,对于出队和入队操作使用CAS非阻塞来实现线程安全的。   1、结构:      ConcurrentLinkedQueue内部的对列使用的是单向链表实现,并且有两个用volatile修改的节点头结点head和tail尾节点    private transient volatile Node<E> head; private transient volatile Node<E> tail; // 默认的无常构造使头节点和尾节点都指向一个值为null的哨兵节点 public ConcurrentLinkedQueue() { head = tail = new Node<E>(null); } // 同时还提供了一个有参构造,将指定集合中的数据插入到链表中 public ConcurrentLinkedQueue(Collection<? extends E> c) { Node<E> h = null, t = null; for (E e : c) { checkNotNull(e); Node<E> newNode = new Node<E>(e); if (h == null) h = t =

java并发编程之美-阅读记录5

為{幸葍}努か 提交于 2019-11-26 20:40:34
java并发包中的并发List 5.1CopeOnWriteArrayList   并发包中的并发List只有CopyOnWriteArrayList,该类是一个线程安全的arraylist,对其进行的修改操作都是在底层的一个复制数组上进行的,也就是使用了写时复制策略。   该类的结构: public class CopyOnWriteArrayList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable { private static final long serialVersionUID = 8673264195747942595L; // 可重入的独占锁,用来保证对arraylist的修改操作,同一时间只有一个线程 final transient ReentrantLock lock = new ReentrantLock(); // 存放对象的底层数组 内存可见性 private transient volatile Object[] array; // 基于硬件的原子操作了Unsafe private static final sun.misc.Unsafe UNSAFE; // 锁的偏移量 private static final long lockOffset; static {

java并发编程之美-阅读记录3

孤者浪人 提交于 2019-11-26 20:01:56
java并发包中的ThreadLocalRandom类,jdk1.7增加的随机数生成器 Random类的缺点:是多个线程使用同一个原子性的种子变量,导致对原子变量的更新产生竞争,降低了效率(该类是线程安全的,但是多线程环境下操作统一实例时,会有效率问题,jdk1.7之后可以使用ThreadLocalRandom类,1.7之前保证多个线程都有一个自己的Random实例即可) protected int next(int bits) { long oldseed, nextseed; // 所谓的种子,即seed原子变量,使用compareAndSet比较修改方式,在多线程环境下,多个线程调用nextInt是会产生竞争,导致效率不高 AtomicLong seed = this.seed; do { oldseed = seed.get(); nextseed = (oldseed * multiplier + addend) & mask; } while (!seed.compareAndSet(oldseed, nextseed)); return (int)(nextseed >>> (48 - bits)); } ThreadLocalRandom的流成类似ThreadLocal,都算是一个工具类,使每一个线程内都有一个自己的副本。 来源: https://www

java并发编程之美-阅读记录4

不打扰是莪最后的温柔 提交于 2019-11-26 20:01:45
java并发包中的原子操作类,这些类都是基于非阻塞算法CAS实现的。 4.1原子变量操作类   AtomicInteger/AtomicLong/AtomicBoolean等原子操作类   AtomicLong类: public class AtomicLong extends Number implements java.io.Serializable { // 基于硬件的原子操作类 private static final Unsafe unsafe = Unsafe.getUnsafe(); // 存放value的偏移地址 private static final long valueOffset; //判断jvm是否支持Long类型无锁CAS static final boolean VM_SUPPORTS_LONG_CAS = VMSupportsCS8(); private static native boolean VMSupportsCS8(); // 初始化value字段的偏移量 static { try { valueOffset = unsafe.objectFieldOffset (AtomicLong.class.getDeclaredField("value")); } catch (Exception ex) { throw new Error(ex)

java并发编程之美-阅读记录2

被刻印的时光 ゝ 提交于 2019-11-26 17:55:36
2.1什么是多线程并发编程   并发:是指在同一时间段内,多个任务同时在执行,并且执行没有结束(同一时间段又包括多个单位时间,也就是说一个cpu执行多个任务)   并行:是指在单位时间内多个任务在同时执行(也就是多个cpu同时执行任务)      而在多线程编程实践中,线程的个数一般是多于cpu的个数的 2.2为什么要多线程并发编程   多个cpu同时执行多个任务,减少了线程上下文切换的开销 2.3线程安全问题   共享资源:就是说该资源可以被多个线程持有,或者说能够被多个线程访问。   对共享资源的修改会造成线程安全问题。 2.4共享变量的内存可见性问题   java内存模型(JMM)规定,所有的变量都存储在主内存中,当线程使用变量时,会将主内存中的变量复制一份到自己的工作内存,之后线程操作的变量都是自己工作内存(L1缓存或者L2缓存或者寄存器)中的变量。   这样对于内存不可见(没有使用volatile修改的变量)的变量来说,在不同线程中就可能存在不同的值。就那下图一个双核cpu系统来说,当操作一个共享变量X时,线程A就会获取当前内存中的变量X,由于线程A是第一次操作,当前工作内存中没有该变量,此时,线程A就会将主内存中的变量X复制一份到自己的工作内存(L1/L2缓存),线程A给变量X重新赋值(假设主内存中默认值为1,线程A修改为2),修改后,线程A会将修改后的值重新刷会主内存