• 面试常见问题小结


    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;
        }
    };

      

     

    ……

  • 相关阅读:
    ajax入门之建立XHR对象 (1)
    JavaScript中的函数有什么特点? 应该怎样优化?
    什么是JavaScript中的面向对象? 与其他编程语言的面向对象有什么区别? 什么是原型?
    Web页面加载,如何分析页面性能?如何进行优化?
    一个页面从输入 URL 到页面加载完的过程中都发生了什么事情?
    关于清除浮动与闭合浮动
    如何更加安全快速的使用富文本编辑器
    用Python实现一个爬取XX大学电费通知的小脚本
    在Sublime Text3上面更加方便愉快的写php
    如何搭建一个WAMP环境
  • 原文地址:https://www.cnblogs.com/Vae1990Silence/p/5036698.html
Copyright © 2020-2023  润新知