面试常见问题小结

1、字符串处理函数  

     strlen(s):返回s的长度,不包括字符串结束符null;

int strlen(const char *str)
{
    assert(str!=NULL);
    int len=0;
    while((*str++)!='')
         len++;
     return len;
}

     Sizeof与Strlen的区别与联系

     sizeof运算符:单目运算符,并不是函数,以字节形式给出了其操作数的存储大小,操作数可以是一个表达式或括在括号内的类型名,操作数的存储大小由操作数的类型决定。需牢记sizeof的计算发生在编译时刻,所以它可以被当作常量表达式使用,且会忽略其括号内的各种运算,如“  sizeof(a++);  ”中的++不执行。

//一般的,在32位编译环境中:
sizeof(int):4
sizeof(short):2
sizeof(long):4
sizeof(float):4
sizeof(double):8
sizeof(char):1
sizeof(p):4   (p为指针)
char  ch3[]="Daniel";
sizeof(ch3)=sizeof("Daniel")=7
strlen(ch3)=6
sizeof("")=2
//可见sizeof计算数据(包括数组、变量、类型、结构体等)所占内存空间,用字节数表示,故将内容为''的数组元素计算在内,而strlen()计算字符数组的字符数,以''为结束标志,且不将''计算在字符数内。

   strcat(dest, src):把src所指字符串添加到dest结尾处(覆盖dest结尾处的‘’)并添加‘’。

     strcpy(dest, src):把从src地址开始且含null结束符的字符串复制到以dest开始的地址空间。

//strcat(dest,src)把src所指字符串添加到dest结尾处(覆盖dest结尾处的'')并添加''
char *strcat(char * strDest, const char *strSrc)
{
    char *res=strDest;
    assert((strDest!=NULL)&&(strSrc!=NULL));
    while(*strDest)strDest++;
    while(*strDest=*strSrc)
    {
        strDest++;
        strSrc++;
    }
    return res;
}
//strcpy(dest,src)把从src地址开始且含有null结束符的字符串复制到以dest开始的地址空间
char *strcpy(char *strDest, const char *strSrc)
{
    char *res=strDest;
    assert((strDest!=NULL)&&(strSrc!=NULL));
    while((*strDest=*strSrc)!='')
    {
        strDest++;
        strSrc++;
    }
    return res;
} 

     memcpy:从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中,函数返回指向dest的指针。

void *memcpy(void *dest, const void *src, size_t n);

  memset:将S中前n个字节用ch替换并返回s,作用是在一段内存块中填充某个给定的值,它是对较大的结构体或数组进行清零操作的一种最快方法。

void *memset(void *s, int ch, size_t n);

  

     strcpy和memcpy的区别:

     1)复制的内容不同:strcpy只能复制字符串,而memcpy可以复制任意内容,例如字符数组、整型、结构体、类等。strcpy只用于字符串复制,并且它不仅复制字符串内容之外,还会复制字符串的结束符。memcpy对于需要复制的内容没有限制,因此用途更广。

     2)复制的方法不同:strcpy不需要指定长度,它遇到被复制字符的串结束符''时才结束,所以容易溢出。memcpy则是根据第三个参数决定复制的长度。

     3)用途不同:通常在复制字符串时用strcpy,而需要复制其他类型数据时则一般用memcpy。

    字符串转换为数字:atoi

enum Status{kValid=0, KInvalid};
int g_nStatus=kValid;
int StrToInt(const char *str)
{
    g_nStatus=KInvalid;
    long long num=0;
    if((str!=NULL)&&(*str!=''))
    {
        bool minus=false;
        if(*str=='+')str++;
        else if(*str=='-')
        {
            minus=true;
            str++;
        }
        if(*str!='')
        {
            num=StrToIntCore(str, minus);
        }
    }
    return (int)num;
}
long long StrToIntCore(const char * digit, bool minus)
{
    long long num=0;
    while(*digit!='')
    {
        if(*digit>='0'&&*digit<=9)
        {
            int flag=minus?-1:1;
            num=10*num+flag*(*digit-'0');
            if(((!minus)&&num>0x7fffffff)||(minus&&(num<(signed int)0x80000000)))
            {
                num=0;
                break;
            }
            digit++;
        }
        else
        {
            num=0;
            break;
        }
    }
    if (*digit=='')
    {
        g_nStatus=kValid;
    }
    return num;
}

2 设计模式-单例模式

//一般单例模式双重锁形式(java):
public class Singleton{
     private  static Singleton instance = null;
     private  Singleton(){}
     public  static Singleton getInstance(){
         if (instance==null){
             synchronized(Singleton.class){
                 if (instance==null){
                     instance=new Singleton();
                 }
             }      
         }
         return instance;
     }
}

3两个栈实现队列的功能    

两个栈实现队列 两个队列实现栈

面试题7:用两个栈实现队列和用两个队列实现一个栈

1)用两个栈实现一个队列。

请实现它的两个函数appendTail和deleteHead,分别完成在队列尾部插入结点和在队列头部删除结点的功能。

解题思路:

插入操作在stack1中进行,删除操作在stack2中进行,如果stack2为空,则将stack1中的所有元素转移到stack2中。

#include<iostream>
#include<stdlib.h>
#include<stack>
using namespace std;

template <typename T>class CQueue
{
public:
    CQueue(void);
    ~CQueue(void);
    void appendtail(const T& node);
    T deleteHead();
private:
    stack<T> stack1;
    stack<T> stack2;

};

//构造函数
template <typename T> CQueue<T>::CQueue(void)
{
}

//析构函数
template <typename T> CQueue<T>::~CQueue(void)
{
}

//插入元素
template <typename T> void CQueue<T>::appendtail(const T& node)
{
    stack1.push(node);
}

//删除元素并返回
template <typename T> T CQueue<T>::deleteHead()
{
    if(stack2.size()<=0)
    {
        while(stack1.size()>0)
        {
            stack2.push(stack1.top());
            stack1.pop();
        }
    }
    if(stack2.size()==0)
        throw new exception("队列为空");
    T head=stack2.top();
    stack2.pop();
    return head;
}

void main()
{
    CQueue<int> queue;
    queue.appendtail(1);
    queue.appendtail(2);
    queue.appendtail(3);
    queue.appendtail(4);
    int len=4;
    while(len>0)
    {
        cout<<queue.deleteHead()<<endl;
        --len;
    }

    system("pause");
}

2)使用两个队列实现一个栈

参考文献:

http://hi.baidu.com/ozwarld/blog/item/ec9b52d4d48ce1dc50da4b0f.html

解法:

  1. 有两个队列q1和q2,先往q1内插入a,b,c,这做的都是栈的push操作。
  2. 现在要做pop操作,即要得到c,这时可以将q1中的a,b两个元素全部dequeue并存入q2中,这时q2中元素为a,b,对q1再做一次dequeue操作即可得到c。
  3. 如果继续做push操作,比如插入d,f,则把d,f插入到q2中,
  4. 此时若要做pop操作,则做步骤2
  5. 以此类推,就实现了用两个队列来实现一个栈的目的。

注意在此过程中,新push进来的元素总是插入到非空队列中,空队列则用来保存pop操作之后的那些元素,那么此时空队列不为空了,原来的非空队列变为空了,总是这样循环。

对于push和pop操作,其时间为O(n).

#include<iostream>
#include<stdlib.h>
#include<stack>
#include<queue>
using namespace std;

template <typename T>class CStack
{
public:
    CStack(void){};
    ~CStack(void){};
    void push(const T& node);
    T pop();
private:
    queue<T> queue1;
    queue<T> queue2;
    
};

//插入元素
template <typename T> void CStack<T>::push(const T& element)
{
    if(queue1.size()>0)//如果queue1不为空则往queue1中插入元素
        queue1.push(element);
    else if(queue2.size()>0)//如果queue2不为空则往queue2中插入元素
        queue2.push(element);
    else//如果两个队列都为空,则往queue1中插入元素
        queue1.push(element);
        
}

//删除元素
template <typename T> T CStack<T>::pop()
{
    if(queue1.size()==0)//如果queue1为空
    {
        while(queue2.size()>1)//保证queue2中有一个元素,将其余元素保存到queue1中
        {
            queue1.push(queue2.front());
            queue2.pop();
        }
        T& data=queue2.front();
        queue2.pop();
        return data;
    }
    else//如果queue2为空
    {
        while(queue1.size()>1)//保证queue2中有一个元素,将其余元素保存到queue1中
        {
            queue2.push(queue1.front());
            queue1.pop();
        }
        T& data=queue1.front();
        queue1.pop();
        return data;
    }

}


void main()
{
    CStack<int> stack;
    stack.push(1);
    stack.push(2);
    stack.push(3);
    stack.push(4);

    int len=4;
    while(len>0)
    {
        cout<<stack.pop()<<" ";
        --len;
    }

    system("pause");
}
//用两个栈实现队列的功能
//假设有两个栈s1与s2,则s1保存刚刚入队的元素,若需出队且s2为空,则将s1所有元素压入s2(此时s2中元素顺序为元素入队顺序),然后取出s2栈顶即可,若s2非空(此时s2中元素为s1之前压入,其栈顶就是最早入队的元素),则直接取出s2的栈顶。
template<class T> class MyQueue
{
    stack<T> s1,s2;
public:
    MyQueue(){}
    int size()
    {
        return s1.size()+s2.size();
    }
    bool empty()
    {
        if(size()==0)return true;
        else return false;
    }
    void push(T value)
    {
        s1.push(value);
    }
    T front()
    {
        if(!s2.empty())
        {
            return s2.top();
        }
        else
        {
            while(!s1.empty())
            {
                s2.push(s1.top());
                s1.pop();
            }
            return s2.top();
        }
    }
    void pop()
    {
        if(!s2.empty())
        {
            s2.pop();
        }
        else
        {
            while(!s1.empty())
            {
                s2.push(s1.top());
                s1.pop();
            }
            s2.pop();
        }
    }
};

4常考排序算法

//直接插入排序
void InsertSort(int A[], int n)
{
    int i,j;
    int temp;
    for (i=0;i<n-1;i++)
    {
        temp=A[i+1];
        j=i;
        while (j>-1&&temp<A[j])
        {
            A[j+1]=A[j];
            j--;
        }
        A[j+1]=temp;
    }
}
//冒泡排序
void BubbleSort(int A[],int n)
{
    int i, j, flag=1;
    int temp;
    for (i=1;i<n&&flag;i++)
    {
        flag=0;
        for (j=0;j<n-i;j++)
        {
            if(A[j+1]<A[j])
            {
                flag=1;
                temp=A[j+1];
                A[j+1]=A[j];
                A[j]=temp;
            }
        }
    }
}
//快速排序
void QuickSort(int A[], int left, int right)
{
    int i=left, j=right;
    int temp=A[left];
    while(i<j)
    {
        while(i<j&&temp<=A[j])j--;
        if(i<j)A[i++]=A[j];
        while(i<j&&A[i]<temp)i++;
        if(i<j)A[j--]=A[i];
    }
    A[i]=temp;
    if(left<i)QuickSort(A,left,i-1);
    if(j<right)QuickSort(A,j+1,right);
}

//快速排序(划分)
int Partition(int A[], int n, int start, int end)
{
    if(A==NULL||n<=0||start<0||end>=n)return -1;
    int index=RandomInRange(start, end);
    swap(&A[index],&A[end]);
    int small=start-1;
    for (index=start; index<end; ++index)
    {
        if(A[index]<A[end])
        {
            small++;
            if(index!=small)
            {
                swap(&A[small],&A[index]);
            }
        }
    }
    small++;
    swap(&A[small],&A[end]);
    return small;
}
void QuickSort(int A[], int n, int left, int right)
{
    if(left==right)return;
    int index=Partition(A, n, left, right);
    if(index>left)
        QuickSort(A,n,left,index-1);
    if(index<right)
        QuickSort(A,n,index+1,right);
}
void getLeastKnum(int A[], int n, int B[], int k)
{
    if(A==NULL||n<=0||B==NULL||k<=0||n<k)return;
    int start=0;
    int end=n-1;
    int index=Partition(A,n,start,end);
    while(index!=k-1)
    {
        if(index>k-1)
            index=Partition(A,n,start,index-1);
        else
            index=Partition(A,n,index+1,end);
    }
    for (int i=0;i<k;i++)
        B[i]=A[i];
}

5旋转有序数组的搜索

/*
1、(无重复)Search in Rotated Sorted Array

Suppose a sorted array is rotated at some pivot unknown to you beforehand.

(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2).

You are given a target value to search. If found in the array return its index, otherwise return -1.

You may assume no duplicate exists in the array.
*/
class Solution {
public:
int search(int A[], int n, int target)
{
        if(A==NULL||n==0)return -1;
        int left=0,right=n-1;
        int mid;
        while(left<=right)
        {
            mid=left+(right-left)/2;
            if(A[mid]==target)return mid;
/*          if(A[mid]==A[left]&&A[mid]==A[right])
            {
                left++;
                right--;
            }
            else*/ if(A[mid]>=A[left])
            {
                if(A[mid]<target)left=mid+1;
                else
                {
                    if(A[left]<=target)right=mid-1;
                    else left=mid+1;
                }
            }
            else
            {
               if(A[mid]>target)right=mid-1;
               else
               {
                   if(A[right]>=target)left=mid+1;
                   else right=mid-1;
               }
            }
        }
        return -1;
}
};
/*
2(有重复)Search in Rotated Sorted Array II

Follow up for "Search in Rotated Sorted Array":
What if duplicates are allowed?

Would this affect the run-time complexity? How and why?

Write a function to determine if a given target is in the array.
*/
class Solution {
public:
    bool search(int A[], int n, int target) {
        if(A==NULL||n==0)return false;
        int left=0,right=n-1;
        int mid;
        while(left<=right)
        {
            mid=left+(right-left)/2;
            if(A[mid]==target)return true;
            if(A[mid]==A[left]&&A[mid]==A[right])
            {
                left++;
                right--;
            }
            else if(A[mid]>=A[left])
            {
                if(A[mid]<target)left=mid+1;
                else
                {
                    if(A[left]<=target)right=mid-1;
                    else left=mid+1;
                }
            }
            else
            {
               if(A[mid]>target)right=mid-1;
               else
               {
                   if(A[right]>=target)left=mid+1;
                   else right=mid-1;
               }
            }
        }
        return false;
    }
};

  

 

……

原文地址:https://www.cnblogs.com/Vae1990Silence/p/5036698.html