常見面試中的算法解法
1、替換空格
解法:如果通過直接遍歷str,找到其中的空格就進行替換,這樣做時間復雜度則為O(n2),那麽我們得想到優化這個替換過程,我們可以先遍歷str得到有多少個空格需要替換,然後從後向前進行遍歷這個str進行替換。
2、從尾到頭打印鏈表
解法一:從頭遍歷鏈表,將遍歷結果依次存進一個棧中,然後再遍歷這個棧,就可以得到這個鏈表從尾到頭每個節點的值
解法二:我們采取遞歸,代碼如下。
3、用兩個棧實現隊列
棧的特點是後進棧先出,隊列是先進棧先出。那麽如果用兩個棧實習的隊列的添加和刪除
a->b 刪除a元素,那麽就將stack1的元素輸出依次放入stack2,輸出stack棧頂,就相當於把隊列的頭刪除了
b->c 如果依然繼續刪除,那麽再將stack2的棧頂彈出就可
d 插入元素,直接放進stack1就可
d->e 如果要刪除元素,先判斷,stack2有沒有元素,如果有直接彈出棧頂就可,如果沒有那麽就想a->b那樣操作刪除元素
4、旋轉數組的最小數字
解析:
用p1和p2指向數組最開始頭和尾,如果p1<p2,這個數組就是有序的,如果p1>=p2,那麽就找到p1、p2中間元素記為mid。如果,mid<p1,則最小元素在mid和p1之間,則讓p2指向mid。反之如果mid>p1,那麽最小元素在mid和p2之間,讓p1指向mid。如果p2-p1=1,那麽這兩個最小的元素就是數組中最小的。
註意:以上解法只適合與不含重復元素的數組中,如果像{0,1,1,1,1}的兩個旋轉數組{1,0,1,1,1}和{1,1,1,0,1}這兩個數組中,是沒法進行二分查找的 因為mid和p1 p2相等,這樣沒法判斷最小元素在mid左側還是右側。這種情況只有采取順序查找。
5、二進制中1的個數
解析:把一個數減去1.在和原整數做與運算,會把該整數最右邊一個1變成0,那麽一個整數的二進制表示中有多少個1,就可以進行多少次這樣的操作。代碼如下:
public static int NumberOf1(int n){ int count=0; while(n != 0){++count; n = (n-1) & n; } return count; }
此題擴展:
6、在O(1)時間段刪除鏈表結點
解題思路:刪鏈表節點,第一時間想到就是遍歷整個鏈表,找到刪除節點的前驅,改變節點指向,刪除節點,但是,這樣刪除單鏈表的某一節點,時間復雜度就是O(n),不符合要求;如果我們考慮用所要刪除結點的數據來替換要刪除的結點數據,並指向刪除結點的下下個結點,最後把要刪除的哪個結點的下一個結點刪掉就完成了。
7、調整數組順序使奇數位於偶數前面
解題思路:
我們讓p1和p2指向數組開頭和結尾 當p1為偶數,p2為奇數時則讓兩個值進行交換,如果不符合,p1往後移。p2往前移,直到p2的位置在p1前面,代碼如下
public static int[] sortArr(int [] arr,int start,int end) { while (start < end) { int temp; if (arr[start] % 2 == 0 && arr[end] % 2 == 1) { temp = arr[start]; arr[start] = arr[end]; arr[end] = temp; ++start; --end; } else if (arr[start] % 2 == 1 || arr[end] % 2 == 1) { ++start; } else { --end; } } return arr; }
8、鏈表中倒數第K個結點
解題思路:如果我們從頭開始遍歷。然後找到倒數第k個,這樣時間復雜度在O(n2),不是最好的解題思路,那麽我們咋做到O(n)的查找呢?很簡單,我們讓兩個指針同時遍歷這個鏈表,這兩個指針相距k個結點,當第一個指針遍歷到尾結點了,那麽就說明後面一個指針遍歷的就是倒數第k個結點。代碼如下:
常見面試中的算法解法