您的位置:首页 > 职场人生

google几道面试题

2012-08-13 13:03 225 查看
1、找规律
1
1 1
2 1
1 2 1 1
1 1 1 2 2 1

下一行是什么?

2、 数列中下一个应该是: 10, 9, 60, 90, 70, 66, ?

A) 96
B) 1000000000000000000000000000000000
0000000000000000000000000000000000
000000000000000000000000000000000
C) Either of the above
D) None of the above

3、有一个特殊的链表,其中每个节点不但有指向下一个节点的指针pNext,还有一个指向链表中任意节点的指针pRand,如何拷贝这个特殊链表?假设其对应的数据结构如下:


struct node
{
int data;
struct node * next;
struct node * random;
};


如图,其中实线表示next域,虚线表示random域。



4、反序一个单向链表 链表数据结构如下:


class Node{
Node* next;
}
// Return the new start after reversion.
Node* ReverseList (Node* start){
}



问题思路分析:

1、其实每一行都是对上一行的“统计”,而且去掉了汉字。 (如何想到的??)
第一行:“1”统计为:1个1,去掉“个”字,就变成了“11”,也就是第二行。
同理,第二行可统计为:2个1,去掉“个”字,就变成了“21”,也就是第三行。
同理,第三行可统计为:1个2和1个1,去掉“个”字和“和”字,就变成了“1211”,也就是第四行。
同理,第四行可统计为:1个1和1个2和2个1,去掉“个”字和“和”字,就变成了“111221”,也就是第五行。
同理,第五行可统计为:3个1和2个2和1个1,去掉“个”字和“和”字,就变成了“312211”,也就是第六行。

2、This can be looked up and found to be sequence A052196 in the On-Line Encyclopedia of Integer Sequences, which gives the largest positive integer whose English name has n letters. For example, the first few terms are ten, nine, sixty, ninety, seventy, sixty-six, ninety-six, …. A more correct sequence might be ten, nine, sixty, googol, seventy, sixty-six, ninety-six, googolplex. And also note, incidentally, that the correct spelling of the mathematical term “google” differs from the name of the company that made up this aptitude test。so the answer of this problem is (A)

3、分析思路可参考:http://blog.sina.com.cn/s/blog_411fed0c0100rrj5.html。 拷贝pNext指针非常容易,所以题目的难点是如何拷贝pRand指针。 一种思路:如果不允许修改L的值,用哈希函数,先依次遍历原链表,每经过一个节点X,开辟一个新节点Y,然后(key=X的地址,value=Y的地址)存入哈希表。第二次再遍历原链表,根据拓扑结构设置新的链表。需要O(n)的空间。另外一种思路:
假设原来链表为A1 -> A2 ->... -> An,新拷贝链表是B1 -> B2 ->...-> Bn。 为了能够快速的找到pRand指向的节点,并把对应的关系拷贝到B中。我们可以将两个链表合并成 A1 -> B1 -> A2 -> B2 -> ... -> An -> Bn。 从A1节点出发,很容易找到A1的pRand指向的节点Ax,然后也就找到了Bx,将B1的pRand指向Bx也就完成了B1节点pRand的拷贝;依次类推。 当所有节点的pRand都拷贝完成后,再将合并链表分成两个链表就可以了。

首先在遍历原来链表的过程中,插入新的节点,比如A_N是拷贝(A_O)的,同时进行操作:(链表插入操作


A_N->next = A_O->next;

A_O->next = A_N;


通过一个遍历,我们就可以将链表复制成下图中的样子。



在完成next域的链接后,需要开始做random域的复制。在实现了next的结构之后,我们需要开始对new_list的random域进行赋值。那么有:


A_N->random = A_O->random->next;

如上图所示:A_O->random为C_O,C_O的next为C_N,这样A_N->random = C_N。



最后再声明一个temp指针,恢复原先链表的next,同时copy到新链表的next。


temp = A_O->next;

A_O->next = temp->next;

temp = temp->next->next;
对于 temp->next = temp->next->next,即B_N。


该算法复杂度为O(N),空间复杂度为O(1),除了新拷贝的空间之外没有额外地址。

具体代码如下:

typedef struct __Node


{


int nData;


__Node* pNext;


__Node* pRandom;


} Node;


Node* DuplicateList(Node* pSrcListHead)


{


if (pSrcListHead == NULL)


return NULL;




 Node* pNode = pSrcListHead;


 // 首先拷贝next域


 while (pNode != NULL)


 {


 Node* pNewNode = new Node;


 pNewNode->nData = pNode->nData;


 pNewNode->pNext = pNode->pNext;


 pNode->pNext = pNewNode;


 //pNewNode->pRandom = pNode->pRandom;




 pNode = pNewNode->pNext; // 递归遍历


}




 Node* pDestListHead = pSrcListHead->pNext;


 pNode = pSrcListHead;


// 完成random域


 while (pNode != NULL)


 {


 pNode->pNext->pRandom = pNode->pRandom->pNext;


 pNode = pNode->pNext->pNext;


}


 


 pNode = pSrcListHead;


 Node* pNode2 = pNode->pNext;


 while (pNode != NULL)


 {


 pNode->pNext = pNode2->pNext;


 pNode = pNode->pNext;


 if (pNode)


 pNode2->pNext = pNode->pNext;


 else


 pNode2->pNext = NULL;


 pNode2 = pNode2->pNext;


}


 return pDestListHead;


}


4、定义两个辅助指针,一个指向当前结点,设为cur;一个指向前一个结点,设为prev,然后反转 cur->next = prev。但是原来的cur->next丢失了。可以再定义一个辅助指针temp,用来保存这个值。另外就是一些为空的判断,需要加倍小心


Node* reverseNode(Node* p)
{

Node *prev= NULL;

Node *cur= p;

//开始反转

while(cur!= NULL)

{

Node *temp= cur->next; //临时保存下一个结点,为了循环遍历的需要

//关键的三步

cur->next = prev;//反转操作

prev= cur;//prev指针移动

cur= temp; //更新当前结点

}

return pPre;//pPre变为第一个结点

}


更多参考资料:

http://coolshell.cn/articles/3345.html

http://zhedahht.blog.163.com/blog/static/254111742010819104710337/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: