笔试面试题整理1

1. 快排的两种写法

以前一直用第一种方式进行快排的,笔试中出现了第二种头尾指针的快排。

第一种:

template<class T,class TCOMP> void quicksort(T a[],int start,int end,TCOMP cmpf=NULL){    int i;    if(start>=end)        return;    int middle = start;    T temp = a[start];    bool flag;    for(i=start+1;i<end;i++)    {        if(cmpf==NULL)            flag = a[i]<temp;        else            flag = cmpf(a[i],temp);        if(flag)            swap(a[++middle],a[i]);    }    swap(a[middle],a[start]);    quicksort(a,start,middle,cmpf);    quicksort(a,middle+1,end,cmpf);}

第二种:

void quicksort2side(int* first,int*last){    if(first>=last)        return;    int *left = first;    int *right = last;    int temp = *first;    while(left<right)    {        while(*right>temp&&right>left)        {            right--;        }        *left = *right;        while(*left<=temp&&left<right)        {            left++;        }        *right = *left;    }    *left = temp;    quicksort2side(first,left-1);    quicksort2side(right+1,last);}

2. 结构体内存对齐问题

这个是非常常见的,笔试面试都很容易被问到,这里总结一下。

typedef struct A{    char a;    char a1[102];}A; //103字节,最后结构体整体按sizeof(char)对齐typedef struct C{    char a;    short b;  //起始地址要2的倍数    char c;    char d;}C;//6字节,最后按short对齐typedef struct B{    char a;    double i;       //起始地址8倍数    short b;}B; //24字节

另外,还有pack和align修饰符的规定。

#pragma pack规定的对齐长度,实际使用的规则是:
结构,联合,或者类的数据成员,第一个放在偏移为0的地方,以后每个数据成员的对齐,按照#pragma pack指定的数值和这个数据成员自身长度中,比较小的那个进行。

当数据定义中出现__declspec( align() )时,指定类型的对齐长度还要用自身长度和这里指定的数值比较,然后取其中较大的。最终类/结构的对齐长度也需要和这个数值比较,然后取其中较大的。

可以这样理解, __declspec( align() ) 和 #pragma pack是一对兄弟,前者规定了对齐的最小值,后者规定了对齐的最大值,两者同时出现时,前者拥有更高的优先级。

3.在循环有序数组中查找某个元素

这个题目比较有意思,在普通有序数组查找直接折半即可,但是循环有序数组还得考虑一下很多问题。因为并不知道循环的起始位置。如下:

123456

234561

456123

//在循环有序数组中查找某个元素,复杂度O(logN)
int find_in_cycle_array(int a[],int n,int elem){ int start =0; int end = n-1; while(start<=end) {  int middle = (start+end)/2;  if(a[middle]==elem)   return middle;  if(a[end]>a[start])  {   if(a[middle]>elem)    end=middle-1;   else    start = middle+1;  }  else  {   if(a[middle]>=a[start])   {    if(a[middle]>elem&&a[start]<=elem)     end = middle-1;    else     start = middle+1;   }   else   {    if(a[middle]<elem&&a[end]>=elem)     start = middle+1;    else     end = middle-1;   }  } } return -1;}
4.获取字符串最长数字串
这个是baidu的一道笔试题,虽然简单,但是要当场写对还是要仔细点。
int getlongestdigital(const char* inputstr,char* outputstr){    int start,length,longeststart,longest,offset;    start = length = longest = longeststart = offset = 0;    while(*inputstr!='\0')    {        if(*inputstr>='0'&&*inputstr<='9')        {            if(length==0)                start = offset;            length++;        }        else        {            if(length>longest)            {                longest = length;                longeststart = start;            }            length =0;        }        offset++;        inputstr++;    }    if(length>longest)    {        longest = length;        longeststart = start;    }    inputstr -= offset;    for(int i=0;i<longest;i++)    {        outputstr[i] = inputstr[i+longeststart];    }    outputstr[longest] = '\0';    return longest;}
5.完全二叉树的节点添加
这个也是常出现的题目,完全二叉树是笔试面试经常碰到的,最好要熟悉的它的各种操作。
typedef struct TreeNode{    int data;    struct TreeNode* left;    struct TreeNode* right;}TreeNode;void insertnode(TreeNode* root,TreeNode* newnode){    queue<TreeNode*> nonvisit;    nonvisit.push(root);    while(!nonvisit.empty())    {        TreeNode* pvisit = nonvisit.front();        nonvisit.pop();        if(pvisit->left==NULL)        {            pvisit->left = newnode;            return;        }        nonvisit.push(pvisit->left);        if(pvisit->right == NULL)        {            pvisit->right = newnode;            return;        }        nonvisit.push(pvisit->right);    }}
6.链表反序 

 
链表是又一个重点,熟悉一下它的各种操作吧
void ReverseList(LinkNode **root){    LinkNode *temp1 = (*root)->next;    if(temp1==NULL)        return;    LinkNode *temp2;    (*root)->next = NULL;    temp2 = temp1->next;    temp1->next = *root;    *root = temp1;    while(temp2!=NULL)    {        temp1 = temp2;        temp2 = temp1->next;        temp1->next = *root;        *root = temp1;    }}
7.
找出最大的一些数,前nums个最大的。

这个题出现的次数还是挺多的,不过大部分都是讲讲思路。基本用快排的思想就行了.

void find_n_most(int* pa,int start,int end,int nums) 
{ 
 if(start>=end-1) 
   return; 
  int i=start;
   for(int j=start+1;j<end;j++)
    {
 if(pa[j]>pa[start])
   swap(pa[j],pa[++i]);
  }
  swap(pa[start],pa[i]);
  if(i==nums-1||i==nums)
    return;
    if(i>nums)
   find_n_most(pa,start,i,nums);
   else
   find_n_most(pa,i+1,end,nums);
 }

上述算法过后,前面nums个数就是所要求的了,注意这个只要求找到前nums个最大的,并不要求排序。

再来一个:

求循环小数的循环体,给两个整数a,b,求a/b的循环小数的循环体字符串,如果不是循环小数则输出空串。

思路:

每次将商追加到结果字符串,记录余数,当余数重复出现时,则从重复的位置开始到最后这一段的商字符串即

string get_circle_digits(unsigned int k,unsigned int j)
2
3 {
4
5    if(k%j==0)
6
7    return "";
8
9    int quotient;
10
11    string quotient_result="";
12
13    vector<int> remainders;
14
15    int remainder = k%j;
16
17    remainders.push_back(remainder);
18
19    while(true)
20
21    {
22
23    quotient = remainder*10/j;
24
25    remainder = remainder*10%j;
26
27    if(remainder==0)
28
29    return "";
30
31    quotient_result.append(1,quotient+'0');
32
33    if(find(remainders.begin(),remainders.end(),remainder)!=remainders.end())
34
35    {
36
37    return quotient_result.substr(find(remainders.begin(),remainders.end(),remainder)-remainders.begin());
38
39    }
40
41    remainders.push_back(remainder);
42
43    }
44
45 }


测试例子:
get_circle_digits(70,11);
get_circle_digits(7,1);
get_circle_digits(1,121);
get_circle_digits(102,9990);
get_circle_digits(1,9);
get_circle_digits(112,999);
原文地址:https://www.cnblogs.com/Leo_wl/p/1743279.html