1. Arrays and Strings

1.1 Hash Tables

哈希表,简单的说就是由一个数组和一个hash函数组成实现key/value映射并且能高效的查找的数据结构。最简单的想法就是将hash(key)做为数组的下标(index)来存取。

但是为了防止hash的冲突(collisions),数组的大小必须设置得足够大,因此上面这种简单的实现在实际中是不可取的。

实际上,哈希表是一个固定大小的数组,数组的每个元素是一个链表(单向或双向)的头指针。每个元素被存放在hash(key)%array_length所在的链表中。如下图所示:

另外,我们可以用二叉查找树(bst)来实现哈希表,在平衡树的基础上能保证0(logn)的查询时间, 而且相对节省空间。

1.2 ArrayList

ArrayList是一个可动态扩张的数组,一个典型的实现就是当ArrayList满了的时候,它会将大小扩大一倍,这个扩张的动作的时间复杂度在O(n),但是发生得很少,所以均摊下来ArrayList的读取复杂度还是O(1)。

1.3 StringBuffer

当考虑进行大量的字符串连接操作的时候,如果使用String中的+操作符来进行,将导致非常糟糕的性能,因为String为不可变对象,一旦被创建,就不能修改它的值。所以下面这条语句

str1 = str1 + str2;

等同于生成了一个新的str1对象,然后将指针指向新的 str1对象,所以经常改变内容的字符串最好不要用String对象 ,因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后,JVM 的 GC 就会开始工作,那速度是一定会相当慢的。

而如果是使用StringBuffer类则结果就不一样了,每次结果都会对StringBuffer对象本身进行操作,而不是生成新的对象,再改变对象引用。StringBuffer上的主要操作是 append 和 insert 方法。append 方法始终将这些字符添加到缓冲区的末端;而 insert 方法则在指定的点添加字符。

所以在一般情况下我们推荐使用StringBuffer,特别是字符串对象经常改变的情况下。而在某些特别情况下, String 对象的字符串拼接其实是被 JVM 解释成了StringBuffer对象的拼接,所以这些时候 String 对象的速度并不会比StringBuffer对象慢,而特别是以下的字符串对象生成中, String 效率是远要比StringBuffer快的:

String s1 = "This is only a" + "simple" + "test";
StringBuffer sb = new StringBuilder("This is only a").append(" simple").append("test");

你会很惊讶的发现,生成 String S1 对象的速度简直太快了,而这个时候StringBuffer居然速度上根本一点都不占优势。其实这是 JVM 的一个把戏,在 JVM 眼里,这个

String s1 = "This is only a" + "simple" + "test";

其实就是:

String s1 = "This is only a simple test";

所以当然不需要太多的时间了。但要注意的是,如果字符串是来自另外的 String 对象的话,速度就没那么快了,譬如:

String S2 = "This is only a";
String S3 = "simple";
String S4 = "test";
String S1 = S2 +S3 + S4;

这时候 JVM 会规规矩矩的按照原来的方式去做。

另外,StringBuilder是5.0新增的一个可变的字符序列。此类提供一个与StringBuffer兼容的 API,但不保证同步。该类被设计用作StringBuffer的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。如果可能,建议优先采用该类,因为在大多数实现中,它比StringBuffer要快。两者的方法基本相同。区别就在于StringBuffer是线程安全的而
StringBuilder
非线程安全。

关于StringBufferStringBuilder的实现:

StringBuffer是一个用于存放动态存放字符串数据的类,他继承自java.lang.AbstractStringBuilder这个类。

所谓动态存放是指:你无需考虑StringBuffer大小的问题。 
当你利用StringBuffer的append方法向其自身添加字符串的时候,如果此时StringBuffer默认提供的空间大小不够用,
那么它会自动扩展自身的存储空间,以保证数据能够正常的放入到StringBuffer其中。

我们也可以手动的设置StringBuffer的空间大小
例如:

StringBuffer buf = new StringBuffer(10); 

上面的意思是指:将StringBuffer的内部容量设置为10个字符(char)大小的长度。

StringBuffer默认的存储空间大小是16个字符,也就是说 new StringBuffer() 就等于 new StringBuffer(16)。 
StringBuffer的底层是利用它的父类(AbstractStringBuilder)内部的一个默认长度为16的字符数组来存放数据的。(即:char value[];)

每当利用 StringBuffer的append方法向其中添加一个字符串的时候StringBuffer都会调用其父类(AbstractStringBuilder)的append方法, 
然后AbstractStringBuilder会判断其内部用于存放数据的那个char[]数组是否已经满了, 
(1)如果没有满,就会将你传入的字符串转化为 
字符并存入到那个字符数组中(即: str.getChars(0, len, value, count);)。 
(2)而如果那个char[]数组已经满了,那么AbstractStringBuilder会创建一个大小为当前数组两倍的新的char[]数组。 
然后利用System.arraycopy(value, 0, newValue, 0, count);将原始数据拷贝到这个新的数组中即可。

CRACKING THE CODING INTERVIEW 笔记(1)的更多相关文章

  1. 《Cracking the Coding Interview》读书笔记

    <Cracking the Coding Interview>是适合硅谷技术面试的一本面试指南,因为题目分类清晰,风格比较靠谱,所以广受推崇. 以下是我的读书笔记,基本都是每章的课后习题解 ...

  2. Cracking the coding interview

    写在开头 最近忙于论文的开题等工作,还有阿里的实习笔试,被虐的还行,说还行是因为自己的水平或者说是自己准备的还没有达到他们所需要人才的水平,所以就想找一本面试的书<Cracking the co ...

  3. Cracking the coding interview 第一章问题及解答

    Cracking the coding interview 第一章问题及解答 不管是不是要挪地方,面试题具有很好的联系代码总用,参加新工作的半年里,做的大多是探索性的工作,反而代码写得少了,不高兴,最 ...

  4. Cracking the Coding Interview(Trees and Graphs)

    Cracking the Coding Interview(Trees and Graphs) 树和图的训练平时相对很少,还是要加强训练一些树和图的基础算法.自己对树节点的设计应该不是很合理,多多少少 ...

  5. Cracking the Coding Interview(Stacks and Queues)

    Cracking the Coding Interview(Stacks and Queues) 1.Describe how you could use a single array to impl ...

  6. Cracking the coding interview目录及资料收集

    前言 <Cracking the coding interview>是一本被许多人极力推荐的程序员面试书籍, 详情可见:http://www.careercup.com/book. 第六版 ...

  7. Cracking the Coding Interview 题目分析笔记—— Array and String

    1.Determine if a string has all unique characters learn: 为了减少空间利用率,其比较优秀的算法一般都适用位操作 返回值的命名方法,我们需要学习 ...

  8. 二刷Cracking the Coding Interview(CC150第五版)

    第18章---高度难题 1,-------另类加法.实现加法. 另类加法 参与人数:327时间限制:3秒空间限制:32768K 算法知识视频讲解 题目描述 请编写一个函数,将两个数字相加.不得使用+或 ...

  9. 《Cracking the Coding Interview》——第13章:C和C++——题目6

    2014-04-25 20:07 题目:为什么基类的析构函数必须声明为虚函数? 解法:不是必须,而是应该,这是种规范.对于基类中执行的一些动态资源分配,如果基类的析构函数不是虚函数,那么 派生类的析构 ...

随机推荐

  1. Invalid file system control data detected

    今天在做mkdir操作时报错:Invalid file system control data detected.检查用户和权限没问题,再检查磁盘空间也没问题.最后在网上找到如下信息: [proble ...

  2. css属性之!important

    提升指定样式规则的应用优先权. IE6及以下浏览器有个比较显式的支持问题存在,!important在同一条规则集里不生效.请看下述代码: div { color: #f00 !important; c ...

  3. UML建模之时序图

    现在是二月,而且到如今你或许已经读到.或听到人们谈论UML 2.0 —— 包括若干进步的 UML 的新规范,所做的变化.考虑到新规范的重要性,我们也正在修改这个文章系列的基础,把我们的注意力从 OMG ...

  4. MFC之CToolTipCtrl按钮提示(消息捕获和消息传递)

    记得以前写对话框时,按钮直接有一个tips属性,可以添加默认值,不记得是C#还是啥了,今天忽然想给几个按钮添加提示信息,就捣鼓了一下. 头文件中创建CToolTipCtrl变量,然后在初始化时激活使用 ...

  5. linux c 之signal 和sigaction区别

    http://blog.csdn.net/muge0913/article/details/7331129 要对一个信号进行处理,就需要给出此信号发生时系统所调用的处理函数.可以对一个特定的信号(除去 ...

  6. css3 渐变linear-gradient

    background: -moz-linear-gradient(top, #FC641C, #FC761C); 参数:其共有三个参数,第一个参数表示线性渐变的方向,top 是从上到下.left 是从 ...

  7. jquery绑定事件on的用法

    语法 $(selector).on(event,childSelector,data,function,map) 参数 描述 event 必需.规定要从被选元素移除的一个或多个事件或命名空间.由空格分 ...

  8. EF中主表和附表一起提交的话,如果主附表的主键外键已经设定。

    EF中主表和附表一起提交的话,如果主附表的主键外键已经设定,如果新增同时新增主表和附表的记录,那么在EF同时提交时,不需要人为的设定附表的主表的主键值,EF会自动为附表添加外键值.

  9. 关于phpmyadmin中添加外键的做法

    今天想加个外键,又不想用命令行,打开PHPMYADMIN看怎么弄,找了半天没有找到添加外键的地方,然后上网搜了一会,发现目前的PHPMYADMIN确实没有这个设置,所以只能手动命令行添加了.   语法 ...

  10. 判断Http请求由手机端发起,还是有电脑端发起

    某些情形,我们需要判断Http请求是来自手机端还是电脑端,关键是取得User-Agent的信息,进行筛选判断即可. 核心类如下: public static boolean isMobileDevic ...