1. 程式人生 > >劍指offer中的程式碼題2.1-2.2

劍指offer中的程式碼題2.1-2.2

Q49:字串轉數字
一般解:

int StrToInt(char* string)
{
    int number=0;
    while(*string !=null)
    {
        number=10*number+*string-‘0’;
        ++string;
    }
    return number;
}
//還要考慮:輸入為空?字串中有非數字?正負數?返回值是int,int的大小限制返回數字的大小,所以輸入的字元是否會造成溢位?

進階解:

Q:求連結串列倒數第K個節點

思路:兩個指標,相差K個節點,一起走,最後一個走到底,另一個就是倒數第K個節點

一般解:

ListNode * FindKthToTail(ListNode * pListHead, unsigned int k)
{
    if(pListHead==NULL) return NULL;
    ListNode *pAhead = pListHead;
    ListNode *pBehind =NULL;
    for(unsigned int i=0;i<k-1;++i)//與while的判斷條件協調
        pAhead=pAhead -> m_pNext;

    pBehind = pListHead;

    while(pAhead -> m_pNext!=NULL)
    {
        pAhead=pAhead -> m_pNext;
        pBehind=pBehind -> m_pNext;
   }
    
    return pBehind;
}
//還要考慮:節點數<k怎麼辦?k為0?

Q:為類CMyString定義一個賦值運算子的函式

注:考慮連續賦值的情況,返回型別應為該型別的引用,並在函式結束前返回例項自身的引用(*this);考慮效率,且複製過程不改變傳入的例項的狀態,所以引數型別為常量引用;考慮記憶體洩漏,是否釋放自身已有記憶體,考慮傳入的引數和當前例項相同,應直接返回,否則釋放自身記憶體的時候會出現找不到需要賦值的內容的操作。

class CMyString
{
public:
    CMyString(char * pData =NULL);
    CMyString(const CMyString & str);
    ~CMyString(void);
private:
    char * m_pData;
};

//初級解
CMyString & CMyString::operator=(const CMyString & str)
{
    if(this ==  & str)
        return *this;
    delete []m_pData;
    m_pData=NULL;
    m_pData= new char[strlen(str.m_pdata)+1]'
    strcpy(m_pData,str.m_pData);
    return *this;
}

//上述方法中,先delete再new,如果記憶體不足導致new的過程中丟擲異常,m_pData將會是一個空指標。
//可以先分配,成功再釋放原始內容,也可以先建立臨時例項,再交換臨時例項和原來的例項

CMyString & CMyString::operator=(const CMyString & str)
{
    if(this !=&str)
    {
        CMyString strTemp(str);

        char* pTemp =strTemp.m_pData;
        strTemp.m_pData=m_pData;
        m_pData=pTemp;
    }
    return *this;
}

Q:設計一個類,只能生成該類的一個例項

解:Singleton


/*初級解
只能生成一個例項,必須把建構函式設定為私有,防止他人建立例項。可以定義一個靜態的例項,在需要的時候建立該例項*/

public sealed class Singleton1
{
    private Singeleton1()//私有
    {
    }
    private static Singleton1 instance =null;//當為null才建立
    public static Singleton1 Instance
    {
        get
        {
            if(instance ==null)
                instance =new Singleton1;
            
            return instance ;
        }
    }
}
/*如果是多執行緒的情況,兩個執行緒同時執行到判斷instance是否為null,如果此時instance沒有建立,那麼連個執行緒都會建立例項,這不滿足單例模式的要求。加鎖*/
public sealed class Singleton2
{
    private Singleton2()
    {}
    private static readonly object syncObj = new object();
    
    private static Singleton2 instance = null;
    public static Singleton2 Instance 
    {
        get
        {
            lock(syncObj)//加鎖耗時,追加判斷條件
            {
                if(instance == null)
                    instance =new Singleton2();
            }
            return instance;
        }
    }
 
}
//兩次判斷
public sealed class Singleton3
{
    private Singleton3()
    {}
    private static readonly object syncObj = new object();
    
    private static Singleton3 instance = null;
    public static Singleton3 Instance 
    {
        get
        {
            if(instance ==null)
            {
            lock(syncObj)//加鎖耗時,追加判斷條件
            {
                if(instance == null)
                    instance =new Singleton2();
            }
            }
            return instance;
        }
    }
 
}
//程式碼太複雜了,利用c#的靜態建構函式,該函式的特性是確保只調用一次
public sealed class Singleton4
{
    private Sinleton4(){}
    private static Sinleton4 instance =new Singleton4;
    public static Singleton4 Instance
    {
        get
        {
            return instance;
        }
    }
}
/*簡潔啊,在初始化靜態變數instance的時候建立了一個例項,c#在呼叫靜態建構函式是初始化靜態變數,.net在執行時能保證只調用一次靜態建構函式,這樣就能保證只初始化一次instance。c#中呼叫靜態建構函式的時機不是程式設計師控制的,當.NET執行時發現,第一次使用一個類的時候,會自動呼叫該類的今天建構函式,也就是說,例項instance並非在呼叫Singleton4.Instance的時候建立,而是在第一次使用到Singleton4的時候就會被建立。如果我們在Singleton4中新增一個靜態方法,該函式不需要建立一個例項,可是按照上述方式實現,會過早建立例項,降低記憶體使用效率*/
public sealed class Singleton5
{
    private Sinleton5(){}
    public static Singleton5 Instance
    {
        get
        {
            return Nest.instance;
        }
    }
    class Nested //巢狀型別
    {
        static Nested()//私有屬性
        {
        }
        internal static readonlu Singleton5 instance =new Singkleton5();
    }
}