[心得]面试题分析与整理2

来源:互联网 发布:智能化数据分析 编辑:程序博客网 时间:2024/05/22 07:55

继续

5.单链表反转,字符串反转

typedef struct node *nodeLink;struct node{    int data;    nodeLink next;};void reverseSigleLink(nodeLink head){    if(!head)   return;    while(head->next)    {        nodeLink tmp = head;        head->next = NULL;        head->next->next = head;        head = tmp;    }}

字符串反转比这个要简单一些,原因是字符串可以直接按位置进行索引。

#include <stdio.h>void myswap(char *ch1, char *ch2){    if (*ch1 == *ch2)   return;    *ch1 = *ch1 + *ch2;    *ch2 = *ch1 - *ch2;    *ch1 = *ch1 - *ch2;}void reverseStr(char *str, int n){    for(int i=0;i<n/2;i++)    {        myswap(&str[i], &str[n-1-i]);    }}int main(){    char str[] = "Hello C.Hello C++..";    printf("raw string is: %s\n", str);    char expect[] = "..++C olleH.C olleH";    printf("expect string is: %s\n\n", expect);    reverseStr(str, sizeof(str)/sizeof(char)-1);    printf("actual output is: %s\n", str);    return 0;}

这个题还引申出一个题,就是把字符串按某个字符进行反转。
比如,
Hello C.Hello C++..
期望的反转结果是:
..Hello C++.Hello C

实际的思路就是再多想一层,既然整体可以做反转,那么局部也可以做反转。
先局部反转分隔符之外的字符,然后再对整体做一次反转,应该可以得到结果。原来的反转函数稍作改造,支持按区间做反转。

#include <stdio.h>void myswap(char *ch1, char *ch2){    if (*ch1 == *ch2)   return;    *ch1 = *ch1 + *ch2;    *ch2 = *ch1 - *ch2;    *ch1 = *ch1 - *ch2;}void reverseStr(char *str, int left, int right){    for(int i=0;i<(right-left)/2;i++)    {        //printf("swap str[%d]:%c <-> str[%d]:%c\n",        //  left+i, str[left+i], right-1-i, str[right-1-i]);        myswap(&str[left+i], &str[right-1-i]);    }}int main(){    char str[] = "Hello C.Hello C++..";    int str_len = sizeof(str)/sizeof(char) -1;    int start = 0;    int end = 0;    printf("raw string is: %s [%d]chars\n", str, str_len);    //char expect[] = "..++C olleH.C olleH";    char expect[] = "..Hello C++.Hello C";    printf("expect string is: %s\n\n", expect);    for(int i=0;i<str_len;i++)    {        if(str[i]=='.' && str[i+1]!='.')        {            start = i+1;        }        if(str[i]!='.' && str[i+1]=='.')        {            end = i;        }        if(start<end)        {            //printf("start=%d, end=%d\n",start, end);            reverseStr(str, start, end+1);            //printf("after partial reverse: %s\n", str);            start = end;        }    }    reverseStr(str, 0, str_len);    printf("actual output is: %s\n", str);    return 0;}

第2段换序列时有点小坑,就是offset要仔细分析。

6.确定两个单链表有共同的部分
这个问题可以演化成判断树有共同祖先的问题,也是面试书上的原题。
基本思路,都往后走,若有共同部分,必然在链表的某个位置会合,如果到尾结点还没会合,那就是没有共同部分,因此这题本质上还是一个单链表的遍历问题。
编程之美233页

#include <iostream>using namespace std;typedef struct Node *NodeLink;struct Node{    int data;    NodeLink next;};NodeLink FindNode(NodeLink a, NodeLink b);NodeLink getTail(NodeLink head);int main(){    NodeLink a, b;    a = b = 0;    FindNode(a, b);    return 0;}NodeLink FindNode(NodeLink a, NodeLink b){    if(!a || !b)     return NULL;    NodeLink tailA = getTail(a);    NodeLink tailB = getTail(b);    if(tailA==tailB)    return tailA;    return NULL;}NodeLink getTail(NodeLink head){    if(!head)   return NULL;    while(head->next)        head = head->next;    return head;}

7.判断一个ip是一个合法的ip
这个题目本质上是一个字符串遍历的问题。解出一段ip,然判断其值是不是合法,当4段ip值都合法,那就是一个合法的ip。

这个问题还有一个引申问法,就是判断两个ip是不是在同一个网段。这个问题本质是考察IP知识,编码倒不是重点。你得知道怎么判断ip,ip和掩码位与结果相同,那才是两个相同的网段。
具体代码略

8.shell排序
这个问题当时被面过,冒泡,选择,插入,快排,堆排,甚至连最复杂的归排都准备了,唯独希尔排序被问了。希尔排序是用步长控制的插入排序,通过加大插入排序的间隔,让数据大幅移动,时间复杂度NlogN。
还是来段代码说话:

void shell_sort(int *a, int n){    int h,j,k,t;    for(h=n/2;h>0;h=h/2)    {        t = a[j];        for(k=j-h;(k>=0)&&t<a[k];k-=h)        {            a[k+h] = a[k];        }        a[k+h] = t;    }}

写起来简单,比快排避开了堆栈调用。

0 0
原创粉丝点击