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

《程序员面试攻略》题目总结

2020-02-18 09:22 155 查看

一. 链表

1. 链表中的倒数第m个元素

给定一个单向链表,请设计一个既节省时间又节省空间的算法来找出该链表中的倒数第m个元素。实现这个算法。
“倒数第m个元素”是这样规定的:当m=0时,链表的最后一个元素(尾元素)将被返回。

前进m步后启动一个“后指针”

2. 空链表和循环链表

给定一个链表,它可能是一个以"NULL"结尾的非循环链表,也可能是一个循环结构结尾的循环链表。写一个函数来判断该链表是一个循环链表还是一个非循环 链表,该函数不得对链表本身做任何修改。

用两个指针,一快一慢,如果是循环链表,快的指针迟早会 超过慢指针,时间复杂度:O(n),最多也是3n

 

int DetermineTermination(node *head)
{
node *fast, *slow;
fast = slow = head;
while(1){
if(!fast || !fast->next){
return 0;
}
else if(fast == slow || fast->next == slow){
return 1;
}
else {
slow = slow->next;
fast = fast->next->next;
}
}
}
 

二. 树和图

1. 树的遍历(递归+非递归)

注意递归转换非递归的分析过程。

2. 最低公共祖先
已知二分查找树上两个节点的值,请找出它们的最低公共祖先。你可以假设这两个值肯定存在。这个函数的调用接口如下所示:

int FindLowestCommonAncestor(node *root, int value1, int value2);
 


原理:两个节点的最低公共祖先的值介于两者之间。
做法:从根节点出发,沿着两个给定节点的公共祖先前进。当这个两个节点的值同时小于当前节点的值时,沿左指针前进;当这两个节点的值同时大于当前节点的值 时,沿右指针前进;当第一次遇到当前节点的值介于两个给定的节点值之间的情况时,这个当前节点就是我们的目标节点。

三. 字符串和数组

1. 第一个无重复字符
采用的方法是哈希表或者数组记录字符的出现次数,然后再从头遍历一次。

2. 颠倒单词的出现顺序
请编写一个函数来颠倒单词在字符串里的出现顺序。比如说,你的函数应该把字符串"Do or do not, there is no try."转化为"try. no is there not, do or Do"。假设所有的单词都以空格为分隔符,标点符号也当做字母来对待。

除了通用性解法外,可以采用一种专用的解法:交换字符, 头尾交换,然后再针对每一个单词头尾交换

void ReverseWords(char str[])
{
int start = 0, end = 0, length;
length = strlen(str);

//
ReverseString(str, start, length-1);

while(end < length){
if(str[end] != ' '){
//Save position of beginning of word
start = end;

//Scan to next non-word character
while(end < length && str[end] != ' '){
end++;
}

//Back up to end of word
end--;

//Reverse words
ReverseString(str, start, end);
}
end++; //Advance to next token
}
return;
}

ReverseString(char str[], int start, int end)
{
char temp;
while(end > start){
temp = str[start];
str[start] = str[end];
str[end] = temp;

start++;
end--;
}
}
 

四. 其他

1. 字节的升序存储和降序存储方式
请编写一个函数还判断某计算机的字节存储顺序是升序(little-endian)还是降序(big-endian)。

“字节的存储顺序”指的是多字节数据的各个字节在计算机里的存储顺序。比如说用来表示整数的那4个字节的顺序,其包括两种,一是按从最低位字节 (LSB)到最高位字节(MSB)的顺序进行存储;另一种是从MSB到LSB的顺序进行存储。这里说的“高位字节”指的是字(word)中的高位字节。如 果字节表示的是字的低值部分,我们就说它是这个字的LSB。比如说,数值“5A6C”中的LSB就是"6C"。反过来说,“5A6C”中的MSB是 “5A”。
在一台采用字节降序存储方案的计算机里,MSB将被保存在最低位的地址里;在一台采用字节升序存储方案的计算机里,LSB将被保存在最低位的地址里。比如 说,采用字节降序存储方案的计算机把十六进制值“A45C”中的"A4"保存在第一个字节里,把"5C"保存在第二个字节里;而一台采用字节升序存储方案 的计算机将把“5C”保存在第一个字节里,把"A4"保存在第二个字节里。

具体到本题中,可以使用字符指针来获取某个字节中的内容。


/* Return 1 if the machine is little-endian, 0 if the
* machine is big-endian
*/
int Endianness(void)
{
int testNum;
char *ptr;

testNum = 1;
ptr = (char *)&testNum;
return (*ptr);
}
 

有一种更精妙的解法,利用了“union”类型:这种类型与 “struct”类似,只是它的所有数据成员都是从内存中的同一个位置开始存储的。这样使你能够把同样的数据当做不同的变量类型来使用。

/* Return 1 if the machine is little-endian, 0 if the
* machine is big-endian
*/
int Endianness(void)
{
union{
int theInteger;
char singleByte;
} endianTest;
endianTest.theInteger = 1;
return endianTest.singleByte;
}
 
  • 点赞
  • 收藏
  • 分享
  • 文章举报
yulianger5 发布了1 篇原创文章 · 获赞 0 · 访问量 89 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: