剑指offer阅读(一)

<h1>数据结构</h1>

<h2>面试题二: 数组</h2>

<blockquote>
数组是一种最简单的数据结构,占据一块连续的数据结构并按照顺序存储数据。创建数组时,我们需要首先指定数组的容量大小,然后根据大小分配内存。
数组的空间利用效率很低,经常会有空闲的区域没有得到充分利用。因为数组中的内存是连续的,因此,他的时间效率很高,可以根据这个优点来实现简单的哈希表,使用数组下标作为哈希表的key,使用下标赌赢的值作为value,这样实现了键值和值的配对。有了这样的哈希表,就可以在O(1)实现查找。
</blockquote>

为了解决数组空间效率不高的问题,人们又实现了多种动态数组。

例:
c++中的STL的vector,为了避免浪费,先为数组开辟较小的空间,然后往数组中添加数据,这样,当数据的数目超过数组的容量时,我们再重新分配一块更大的空间,然后把之前的数据复制到新的数组中,然后把之前的内存释放掉。

<pre><code>int GetSize(int data[]){
return sizeof(data);
}

int _tmain(int argc,_TCHAR* argv[]){
int data1[] = {1,2,3,4,5};
int size1 = sizeof(data1);

int* data2 = data1;
int size2 = sizeof(data2);

int size3 = GETSize(data1);

printf("%d,%d,%d",size1,size2,size3);

}
</code></pre>

答案是“20,4,4”

一个整数是4字节,在C/C++中,当数组作为参数被传递时,它就会退化成指针,所以也占4字节。

<h2>面试题三:二维数组的查找</h2>

<blockquote>
在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
</blockquote>

<pre><code><br />bool Find(int* matrix,int rows,int columns,int number){
bool found = false;

if(matrix != NULL &amp;&amp; rows &gt; 0 &amp;&amp; columns &gt;0){
    int row = 0;
    int column = columns - 1;
    while(row&lt;rows&amp;&amp;column &gt;= 0){
        if(matrix[row * columns +column]==nulber){
            found = true;
            break;
        }else if(matrix[row * columns + column] &gt; number)
            --column;
        else 
            ++ row;
    }
}

}
</code></pre>

<pre><code class="Java"> private static boolean find(int[][] m, int target) {
boolean result = false;
if (m != null){
int lie = m[0].length-1;
for (int i = m[0].length-1;i > 0;i--){
if (m[0][i]<=target){
lie = i;
break;
}
}
for (int i = 0;i<m.length-1;i++){
if (m[i][lie]==target){
result = true;
}
}

    }
    return result;
}

</code></pre>

<h2>面试题四:替换空格</h2>

字符串

Java中对象作为参数传递时,是把对象在内存中的地址拷贝了一份传给了参数。

参数的值就是对该对象的引用,而不是对象的内容。

<ol>
<li>先遍历一次字符串,得出空格的个数,计算出替换后的字符串长度</li>
<li>准备两个指针P1和P2,P1指向原始字符串的末尾,P2指向替换之后的字符串的末尾</li>
<li>向前移动P1,逐个复制到P2的位置,直到遇到空格,在P2之前插入“%20”</li>
<li>直到P1和P2指向同一位置,表明所有空格都已替换完毕。</li>
<li>所有的字符都只复制1次,复杂度为O(n)</li>
</ol>

<pre><code class="java"><br />void ReplaceBlank(char string[],int length){
if(string == null||length <= 0){
return;
}
/originalLength为字符串string的实际长度/
int originalLength = 0;
int numberOfBlank = 0;
int i = 0;
while(string[i]!='\0'){
++ originalLength;
if(string[i] == ' '){
++ numberOfBlank;
}
++ i;
}
newLength为把空格替换为'%20'的长度
int newLength = originalLength + numberOfBlank * 2;
if(newLength > length)
return;
int indexOfOriginal = originalLength;
int indexOfNew = newLength;
while(indexOfOriginal >= 0 && indexOfNew > indexOfOriginal){
if(string[indexOfOriginal] == ' '){
string[indexOfNew --] = '0';
string[indexOfNew --] = '2';
string[indexOfNew --] = '%';
}else{
string[indexOfNew --] = string[indexOfOriginal];
}
-- indexOfOriginal;
}
}

</code></pre>

<h2>面试题五:从尾到头打印链表</h2>

<blockquote>
链表是一种动态的数据结构
</blockquote>

<pre><code class="cpp">//单向链表
struct ListNode{
int m+nvalue;
ListNode* m_pNext;
}
</code></pre>

<pre><code class="cpp">//pHead是一个只想指针的指针,当我们往一个空链表中差入一个节点时,新插入的节点就是链表的头指针,当我们往一个空链表中插入一个节点时,新插入的节点就是链表的头指针。此时会改变头指针,因此必须把pHead射程为指向指针的指针。
void addToTail(ListNode** pHead,int value){
ListNode* pNew = new ListNode();
pNew->m_nvalue = value;
pNew->m_pNext = NULL;
if(*pHead){
pHead = pNew;
}else{
ListNode
pNode = *pHead;
while(pNode->m_pNext != NULL){
pNode = pNode->m_pNext;
}
pNode->m_pNext = pNew;
}
}
</code></pre>

<pre><code>//在链表中找到某值并删除
void RemoveNode(ListNode** pHead,int value){
if(pHead == NULL||*pHead == NULL)
return;

ListNode* pToBeDeleted = NULL;
if((*pHead)-&gt;m_nValue==value){
    pToBeDeleted = *pHead;
    *pHead = (*pHead)-&gt;m_pNext;
}else{
    ListNode* pNode = *pHead;
    while(pNode-&gt;m_pNext !=NULL&amp;&amp;pNode-&gt;m_pNext-&gt;m_nValue!=value){
        pNode = pNode-&gt;m_pNext;
    }
    if(pNode-&gt;m_pNext != NULL &amp;&amp; pNode-&gt;m_pNext-&gt;m_nValue == value){
        pToBeDeleted = pNode-&gt;m_pNext;
        pNode -&gt; pNode-&gt;m_pNext-&gt;m_pNext;
    }
}
if(pToBeDeleted != NULL){
    delete pToBeDeleted;
    pToBeDeleted = NULL;
 }

}

</code></pre>

<blockquote>
输入一个链表的头节点,从尾到头打印出每个节点的值
</blockquote>

<pre><code><br />struct ListNode{
int m_nKey;
ListNode* m_pNext;
}
</code></pre>

<pre><code><br />public static void getList(LinkedList<Integer> list) {
if (list == null)
return;
Stack<Integer> stack = new Stack<>();
while (!list.isEmpty()) {
Integer i = list.getFirst();
stack.push(i);
list.removeFirst();
}
while (!stack.isEmpty()) {
System.out.println(stack.pop());
}
}
</code></pre>

<h2>面试题六:重建二叉树</h2>

遍历:

<ul>
<li>前序遍历 先访问根节点,再访问左子节点,最后访问右子节点</li>
<li>中序遍历 先访问左子节点,再访问根节点,最后访问右子节点</li>
<li>后序遍历 先访问左子节点,再访问右节点,最后访问根子节点</li>
</ul>

<pre><code class="java"><br />class TreeNode<T> {
private T data;
private TreeNode<T> leftNode;
private TreeNode<T> rightNode;

    public TreeNode(T data, TreeNode&lt;T&gt; leftNode, TreeNode&lt;T&gt; rightNode) {  
        this.data = data;  
        this.leftNode = leftNode;  
        this.rightNode = rightNode;  
    }  


    public T getData() {  
        return data;  
    }  

    public void setData(T data) {  
        this.data = data;  
    }  

    public TreeNode&lt;T&gt; getLeftNode() {  
        return leftNode;  
    }  

    public void setLeftNode(TreeNode&lt;T&gt; leftNode) {  
        this.leftNode = leftNode;  
    }  

    public TreeNode&lt;T&gt; getRightNode() {  
        return rightNode;  
    }  

    public void setRightNode(TreeNode&lt;T&gt; rightNode) {  
        this.rightNode = rightNode;  
    }  

}  

</code></pre>

前序遍历

<h4>递归</h4>

<pre><code class="java">public void preIterator(TreeNode<String> node){
this.printNode(node);
if(node.getLeftNode()!=null){
this.preIterator(node.getLeftNode());
}
if(node.getRightNode()!=null){
this.preIterator(node.getRightNode());
}
}
</code></pre>

<h4>非递归</h4>

<pre><code class="java">public void preIterator2(TreeNode<String> node){
Stack<TreeNode<String>> stack = new Stack();
if(node!=null){
stack.push(node);
while(!stack.isEmpty()){
node = stack.pop();
this.printNode(node);
if(node.getRight()!=null)
stack.push(p.getRight());
if(node.getLeft()!=null)
stack.push(p.getLeft());
}
}
}
</code></pre>

<h3>中序遍历</h3>

<h4>递归</h4>

<pre><code class="java">public void midleIterator(TreeNode<String> node){
if(node.getLeftNode!=null){
this.midleIterator(node.getLeftNode);
}
this.printNode(node);
if(node.getRightNode!=null){
this.midleIterator(node.getRightNode);
}
}
</code></pre>

<h4>非递归</h4>

<pre><code class="java">protected static void midleIterator(TreeNode node){
Stack<TreeNode> stack = new Stack();
while(node!=null||stack.size()>0){
while(node!=null){
stack.push(node);
node = node.getLeft();
}
if(stack.size()>0){
node = stack.pop();
this.printNode(node);
node = node.getRight();
}
}
}

</code></pre>

<h3>后序遍历</h3>

<h4>递归</h4>

<pre><code class="java">public void lastIterator(TreeNode<String> node){
if(node.getLeftNode()!=null){
this.printNode(node.getLeftNode());
}
if(node.getRightNode()!=null){
this.printNode(node.getRightNode());
}
this.printNode(node);
}
</code></pre>

<h4>非递归</h4>

<pre><code class="java">public static void lastIterator(TreeNode node){
Stack<TreeNode> stack = new Stack();
while(node!=null||!stack.isEmpty()){
while(node!=null){
stack.push(node);
node = stack.pop();
}
if(!stack.isEmpty()){
Node temp = stack.peek().getRight();
if(temp == null || temp == prev){
node = stack.pop();
this.printNode(node);
prev = node;
node = null;
}else{
node = temp;
}
}
}
}

</code></pre>

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,392评论 5 470
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,258评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,417评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,992评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,930评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,199评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,652评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,327评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,463评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,382评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,432评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,118评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,704评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,787评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,999评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,476评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,057评论 2 341

推荐阅读更多精彩内容

  • 1.把二元查找树转变成排序的双向链表 题目: 输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。 要求不...
    曲终人散Li阅读 3,277评论 0 19
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,537评论 18 399
  • 1 序 2016年6月25日夜,帝都,天下着大雨,拖着行李箱和同学在校门口照了最后一张合照,搬离寝室打车去了提前租...
    RichardJieChen阅读 5,068评论 0 12
  • 逃避,不闻不问,淡漠,置身事外,正常吗?
    Sara_馨阅读 108评论 0 0
  • 一个人久了,以为爱情不是必需品,结婚也不是非做不可的事情。但是有一些爱情故事却总是会改变我的看法。 随着身边的朋友...
    王大闲人阅读 678评论 2 7