高質量的代碼

double類型的比較不能用==ios

計算機表示的小數(包括float & double)都有偏差,若是兩個小數的差的絕對值很小,小雨0.0000001(中間爲6個0)就能夠認爲他們相等git

完整的代碼:功能測試,邊界測試,負面測試面試

考慮題目是否會出現大數問題,超出int的能夠用long long
負面測試是指輸入的數據是非法的錯誤的
 
3種錯誤處理方法:


1.不一樣的返回值表示不一樣的錯誤算法

2.
3.拋出異常時,程序的執行會打亂正常的順序,對程序的性能有很大的影響。
 


 

面試題11:數值的整數次方編程

 注意各類輸入,base爲0.0,exponent爲負數時是錯誤輸入數組

 exponent爲負數,取絕對值,求冪後倒數,網絡

 注意浮點數的比較相等用差值和0.0000001ide

 求冪用遞歸,a的n次方分奇偶考慮,偶數的時候就用a的n/2的平方函數

 除以2的時候用位移,體現細節..性能

 

面試題12:打印1到最大n位數

n位數可能會超出long long的範圍,long long 爲8字節64位

-->用字符串模擬數字的加法 

複製代碼
  1  
  2  /*n位數可能會超出long long的範圍,long long 爲8字節64位
  3      -->用字符串模擬數字的加法*/
  4  #include <memory>
  5  #include <string.h>
  6  //C++ 中要使用strlen通常包含<CString>
  7  
  8  //一直進位直到第一次結束纔是一個+1過程的結束
  9  bool Increment(char* number)
 10  {
 11      int length = strlen(number);
 12      int takeOver = 0;
 13      bool isOverStack = false;
 14      
 15      for(int i = length - 1; i >= 0; ++i)
 16      {
 17          int sum = number[i] - '0' + takeOver;
 18          if(i == length - 1)
 19              ++sum;
 20  
 21          if(sum >= 10)
 22          {
 23              if(i == 0)
 24                  isOverStack = true;
 25              else
 26              {
 27                  sum -= 10;
 28                  number[i] = sum + '0';
 29                  takeOver = 1;
 30              }
 31          }
 32          else
 33          {
 34              number[i] = sum + '0';
 35              break;
 36          }
 37  
 38      }
 39      return isOverStack;
 40  }
 41  
 42  //不要打印出最前面的0
 43  void PrintNumber(char* number)
 44  {
 45      int length = strlen(number);
 46      bool posFlag = false;
 47  
 48      for(int i = 0; i < length; ++i)
 49      {
 50          if(!posFlag && number[i] != '0')
 51              posFlag = true;
 52          if(posFlag)
 53              printf("%c", number[i]);
 54      }
 55      return;
 56  }
 57  
 58  void PrintToMaxOfNDigits(int n)
 59  {
 60      if(n <= 0)
 61          return;
 62      char *number = new char[n + 1];
 63      memset(number, '0', n);
 64      number[n] = '\0';
 65  
 66      while(!Increment(number))
 67          PrintNumber(number);
 68      delete []number;
 69  }
 70  
 71  //把問題轉換爲數字排列的方法,運用遞歸是程序更加簡單
 72  //全排列方法
 73  
 74  void PrintToMaxOfNDigits_1(int n)
 75  {
 76      char* number = new char[n + 1];
 77      memset(number, '0', n);
 78      number[n] = '\0';
 79      for(int i = 0; i < 10; ++i)
 80      {
 81          number[0] = '0' + i;
 82          PrintRecursively(number, n, 0)
 83      } 
 84      delete []number;
 85  }
 86  
 87  void PrintRecursively(char* number, int length, int index)
 88  {
 89      if(index == length - 1)
 90      {
 91          PrintNumber(number);
 92          return;
 93      }
 94  
 95      for(int i = 0; i < 10; ++i)
 96      {
 97          number[index + 1] = '0' + i;
 98          PrintRecursively(number, length, index + 1);
 99      }
100  }
複製代碼

 

 

 面試題13:在O(1)時間內刪除鏈表節點

把下一個節點的內容複製到須要刪除的節點上覆蓋原有的內容,再把下一個節點刪除便可。

若刪除的節點位於列表尾部則順序遍歷獲得該節點的前序節點,並完成刪除操做。

若是鏈表中只有一個節點,則在刪除後還須要把鏈表的頭結點設置爲NULL。

//題目已經假設刪除的節點必定在鏈表中

//節點delete以後,要將自己設爲NULL,position自己就是一個節點指針,是有指向的

複製代碼
 1 #include <iostream>
 2 using namespace std;
 3 
 4 typedef struct ListNode* head;
 5 typedef struct ListNode* position;
 6 struct ListNode
 7 {
 8     int m_nValue;
 9     ListNode* m_pNext;
10 };
11 
12 void DeleteNode(head pListHead, position pToBeDeleted)
13 {
14     if(!pListHead || !pToBeDeleted)
15         return;
16     position pTemp;
17     if(pToBeDeleted->m_pNext == NULL)
18     {
19         pTemp = pListHead;
20         while(pTemp->m_pNext != pToBeDeleted)
21             pTemp = pTemp->m_pNext;
22         pTemp->m_pNext = pToBeDeleted->m_pNext;
23         delete pToBeDeleted;
24         //注意下面一行
25         pToBeDeleted = NULL;
26         return;
27     }
28     pTemp = pToBeDeleted->m_pNext;
29     pToBeDeleted->m_nValue = pTemp->m_nValue;
30     pToBeDeleted->m_pNext = pTemp->m_pNext;
31     delete pTemp;
32     //注意下面一句
33     pTemp = NULL;
34     return;
35 }
複製代碼

面試題14:調整數組順序使奇數位位於偶數以前

題目:輸入一個整數數組,調整數組中數字的順序,使得全部奇數位於數組的前半部分,全部偶數位於數組的後半部分。要求時間複雜度爲O(n)。

用和快排比較類似的算法,維護兩個指針

一般狀況下位運算符比%要快一些,因此判斷奇偶能夠用data & 0X1 比較好

 

複製代碼
 1 #include<iostream>
 2 using namespace std;
 3 void ReorderOddEven(int *number, unsigned int length)
 4 {
 5     //函數初始時基本的判斷參數輸入有沒有錯誤的不要忘了!!!
 6     if(number == NULL || length == 0)
 7         return;
 8 
 9     int *p1 = number, *p2 = number + (length -1);
10     while(p1 < p2)
11     {
12         while(p1 < p2 && (*p1 & 0x1) == 1)
13             ++p1;
14         while(p1 < p2 && (*p2 & 0x1) == 0)
15             --p2;
16         if(p1 < p2)
17         {
18             int temp = *p1;
19             *p1 = *p2;
20             *p2 = temp;
21         }
22         
23     }
24     return;
25 }
複製代碼

 

能夠利用函數指針把這個算法擴展

複製代碼
 1 void Reorder(int* number, unsigned int length, bool (*func)(int))
 2 {
 3     //函數初始時基本的判斷參數輸入有沒有錯誤的不要忘了!!!
 4     if(number == NULL || length == 0)
 5         return;
 6 
 7     int *p1 = number, *p2 = number + (length -1);
 8     while(p1 < p2)
 9     {
10         while(p1 < p2 && !func(*p1))
11             ++p1;
12         while(p1 < p2 && func(*p2))
13             --p2;
14         if(p1 < p2)
15         {
16             int temp = *p1;
17             *p1 = *p2;
18             *p2 = temp;
19         }
20 
21     }
22     return;
23 }
24 
25 bool isEven(int n)
26 {
27     return (n & 0x1) == 0;
28 }
29 void ReorderOddEven2(int* number, unsigned int length)
30 {
31     Reorder(number, length, isEven);
32 }
複製代碼

 

代碼的魯棒性:

容錯性是代碼魯棒性的一個重要體現

1.輸入錯誤的用戶名

2.試圖打開不存在的文件

3.網絡不能鏈接

4......

-->預防性編程

 

面試題15:鏈表中倒數第k個結點

題目:輸入一個單向鏈表,輸出該鏈表中倒數第k個結點。鏈表的倒數第0個結點爲鏈表的尾指針。鏈表結點定義以下:

記尾節點是倒數第一個節點,

用unsigned int 來表示length比較合理,此時0 - 1獲得一個巨大的數

複製代碼
 1 #include <iostream>
 2 using namespace std;
 3 typedef struct ListNode* phead;
 4 typedef struct ListNode* position;
 5 struct ListNode
 6 {
 7     int m_nValue;
 8     ListNode* m_pNext;
 9 };
10 
11 position FindKthNode(phead listHead, unsigned int k)
12 {
13     if(listHead == NULL || k == 0)
14         return NULL;
15     position temp1 = listHead, temp2 = listHead;
16 
17     for(unsigned int i = 0; i < k - 1; ++i)
18     {
19         if(temp1->m_pNext != NULL)
20             temp1 = temp1->m_pNext;
21         else
22             return NULL;
23     }
24     while(temp1->m_pNext != NULL)
25     {
26         temp1 = temp1->m_pNext;
27         temp2 = temp2->m_pNext;
28     }
29     return temp2;
30 }
複製代碼

要注意K=0,listHead指向空,list長度小於K

1.求鏈表的中間節點:

  若鏈表總數爲奇數,返回中間節點,不然返回中間節點2箇中的任意一個

  定義兩個指針都從鏈表頭結點出發,一個一次走一步,一個一次走兩步,走的快的到末尾時,走的啊,慢的恰好在鏈表的中間

2.判斷一個鏈表是否構成環形;

  同上,定義兩個指針都從鏈表頭結點出發,一個一次走一步,一個一次走兩步,走的快若是能追上走的慢的那麼就是環形鏈表,若是到鏈表末尾尚未追上走的慢的則不是環形鏈表

 

當咱們使用一個指針遍歷鏈表不能解決問題的時候,能夠嘗試用兩個指針來遍歷,兩個指針遍歷的速度或者前後不一樣。

 

面試題16:反轉鏈表

輸入的鏈表指針爲NULL或者整個鏈表只有一個節點

反轉後頭結點是否是鏈表的原先的尾節點

複製代碼
 1 #include<iostream>
 2 using namespace std;
 3 typedef struct ListNode* pHead;
 4 typedef struct ListNode* position;
 5 
 6 struct ListNode
 7 {
 8     int m_nValue;
 9     ListNode* m_pNext;
10 };
11 
12 pHead ReverseList(pHead listHead)
13 {
14     pHead pReversedHead = NULL;
15     position pNode = listHead;
16     position pPrev = NULL;
17 
18     //這種形式中頭結點不是啞元,反轉後頭結點爲的下一個爲NULL
19     //因此初始的pPrev設爲NULL
20     
21     while(pNode != NULL)
22     {
23         position pNext = pNode->m_pNext;
24         if(pNext == NULL)
25             pReversedHead = pNode;
26 
27         pNode->m_pNext = pPrev;
28         pPrev = pNode;
29         pNode = pNext;
30     }
31     return pReversedHead;
32 }
複製代碼

遞歸實現注意頭結點的6,7,8行是最後實現的

複製代碼
1 Node * resverselinkRecursion(Node *head) 
2 {
3  if(head==NULL || head->next==NULL)
4   return head;
5  Node *n = resverselinkRecursion(head->next);
6  head->next->next = head;
7  head->next=NULL;
8  return n;
9 }
複製代碼

 

 面試題18:樹的子結構

判斷二叉樹B是否是A的子結構

複製代碼
 1 #include<iostream>
 2 using namespace std;
 3 
 4 typedef struct BinaryTreeNode* position;
 5 typedef struct BinaryTreeNode* root;
 6 struct BinaryTreeNode
 7 {
 8     int            m_nValue;
 9     position    m_pLeft;
10     position    m_pRight;
11 };
12 
13 bool HasSubTree(root pRoot1, root pRoot2)
14 {
15     bool result = false;
16     if(pRoot1 != NULL && pRoot2 != NULL)
17     {
18         if(pRoot1->m_nValue == pRoot2->m_nValue)
19             result = DoesTree1HaveTree2(pRoot1, pRoot2);
20         if(!result)
21             result = HasSubTree(pRoot1->m_pLeft, pRoot2);
22         if(!result)
23             result = HasSubTree(pRoot1->m_pRight, pRoot2);
24     }
25     return result;
26 }
27 
28 bool DoesTree1HaveTree2(root pRoot1, root pRoot2)
29 {
30     if(pRoot2 == NULL)
31         return true;
32     if(pRoot1 == NULL)
33         return false;
34     if(pRoot1->m_nValue != pRoot2->m_nValue)
35         return false;
36     return DoesTree1HaveTree2(pRoot1->m_pLeft, pRoot2->m_pLeft) &&
37         DoesTree1HaveTree2(pRoot1->m_pRight, pRoot2->m_pRight);
38 }
複製代碼

 

樹的操做都伴隨着大量的指針,尤爲要考慮清楚是否爲NULL的狀況。

相關文章
相關標籤/搜索