复习一下<程序员面试攻略>,并记录一些心得.

链表:
1. 找到单链表中倒数第m个元素
方法:使用两个指针,这两个指针相距m个元素,然后使得两个指针同步前进,当后一个指针到空时,前一个指针即为倒数第m个元素
实现:
elem* FindMToLastElem(elem* head,  int m)
{
    elem* current, mbehind;
    current = head;
     for( int i=0; i<m; i++)
    {
         if(current->next)
        {
            current = current->next;
        }
         else
        {
             return NULL;
        }
    }
    
    mbehind = head;
     while(current->next)
    {
        current = current->next;
        mbehind = mbehind->next;
    }

     return mbehind;
}

2. 判断一个链表为循环链表还是非循环链表

方法:使用快慢指针,快指针每次走两步,慢指针每次走一步,若快指针到达NULL,则为非循环链表,若快指针超过了慢指针,则为循环链表
实现:
int determin_termination(node* head)
{
    node* fast, slow;
     if(!head || !(head->next))
    {
         return 0;
    }
    fast = head->next->next;
    slow = head->next;
     while(1)
    {
         if(!fast || !(fast->next))
        {
             return 0;
        }
         else  if(fast == slow || fast->next == slow)
        {
             return 1;
        }
         else
        {
            fast = fast->next->next;
            slow = slow->next;
        }
    }
}

树和图:
1. 二叉树前序遍历的非递归算法
方法:使用堆栈
实现:
void PreorderTraversal(node* head)
{
    elem* stack;
    CreateStack(&stack);
    Push(&stack, head);
    
    node* pNode;
     while(Pop(&stack, &pNode)
    {
         if(NULL != pNode)
        {
            printf("%d\n", pNode->value);
            Push(&stack, pNode->right);
            Push(&stack, pNode->left);
        }
    }
    DeleteStack(&stack);
}

数组和字符串:
1. 高效删除特定字符
方法:每次删除字符时不在数组中移动字符串,而是直接拷贝到之前扫描过的位置中。另外采用数组来减少字符串比较次数。
void RemoveChars( char str[],  char remove[])
{
     //  create an array for remove characters
     char removeArray[256];
     for( int i=0; i<256; i++)
    {
        removeArray[i] = 0;
    }
     int src = 0;
     while(remove[src])
    {
        removeArray[remove[src]] = 1;
        src++;
    }
     int dest = 0;
    src = 0;
     do
    {
         if(!removeArray[remove[src]])
        {
            str[dest++] = str[src];
        }
    } while(str[src++]);
    
}

2. 颠倒单词出现的次序
Do or do not, there is no try. 转换为 try. no is there not, do or Do
方法:先将整个字符串颠倒,再将新字符串中的每个单词颠倒

3. 编写字符串和数字相互转换函数
int Str2Int( char* str)
{
     int num = 0, neg = 1, i = 0;
     if(str[0] == '-')
    {
        neg = -1;
        i = 1;
    }
    
     while(str[i])
    {
        num = num * 10 + str[i++] - '0';
    }
    num = num * neg;
     return num;
}

void Int2Str( int num,  char str[])
{
     int neg = 1;
     if(num < 0)
    {
        num *= -1;
        neg = -1;
    }
    
     int i = 0;
     do
    {
        str[i++] = num % 10 + '0';
        num = num / 10;
    } while(num)

     if(neg == -1)
    {
        str[i++] = '-';
    }
    str[i] = 0;
    
     for( int j = 0; j < i/2; j++)
    {
        str[j] = str[i-1-j];
    }
    
}