第二十五題:複雜鏈表的複製
題目描述:
輸入一個複雜鏈表(每個節點中有節點值,以及兩個指標,一個指向下一個節點,另一個特殊指標指向任意一個節點),返回結果為複製後複雜鏈表的head。(注意,輸出結果中請不要返回參數中的節點引用,否則判題程式會直接返回空)
思路:
第一步:掃描原鏈表,把複製的結點就連在原結點的後面;例如:(原鏈表)A->B->C —–> A->A’->B->B’->C->C’
第二步:掃描原鏈表,如果結點有random指向,則把對應的複製結點的random指向對應的複製結點;例如:A指向C,則把A’指向C’。因為都是連在一個鏈表上的,所有能以o(1)的時間複雜度找到。
第三步:
分離兩個鏈表,注意null 指標的指向即可。
代碼:
/*public class RandomListNode { int label; RandomListNode next = null; RandomListNode random = null; RandomListNode(int label) { this.label = label; }}*/public class Solution { public RandomListNode Clone(RandomListNode pHead) { if (pHead == null) { return null; } clone(pHead); random(pHead); return getRandomListNode(pHead); } public void clone(RandomListNode pHead){ while (pHead != null) { RandomListNode cloneNode = new RandomListNode(pHead.label); cloneNode.next = pHead.next; pHead.next = cloneNode; pHead = cloneNode.next; } } public void random(RandomListNode pHead) { while (pHead != null) { if (pHead.random != null) { pHead.next.random = pHead.random.next; } pHead = pHead.next.next; } } public RandomListNode getRandomListNode(RandomListNode pHead) { RandomListNode p1 = pHead.next; RandomListNode ret = pHead.next; pHead.next = p1.next; pHead = pHead.next; while (pHead != null) { p1.next = pHead.next; p1 = p1.next; pHead.next = p1.next; pHead = pHead.next; } return ret; }}
第二十六題:二叉搜尋樹與雙向鏈表
題目描述:
輸入一棵二叉搜尋樹,將該二叉搜尋樹轉換成一個排序的雙向鏈表。要求不能建立任何新的結點,只能調整樹中結點指標的指向。
思路:
由於是二叉搜尋樹,要轉換成一個排序的雙向鏈表,那麼對這棵二叉樹進行中序遍曆得到的排序的鏈表。
代碼:
/**public class TreeNode { int val = 0; TreeNode left = null; TreeNode right = null; public TreeNode(int val) { this.val = val; }}*/public class Solution { protected TreeNode lastLeft = null; public TreeNode Convert(TreeNode pRootOfTree) { if (pRootOfTree == null) { return null; } if (pRootOfTree.left == null && pRootOfTree.right == null) { lastLeft = pRootOfTree; return pRootOfTree; } TreeNode left = Convert(pRootOfTree.left); if (lastLeft != null) { pRootOfTree.left = lastLeft; lastLeft.right = pRootOfTree; } lastLeft = pRootOfTree; TreeNode right = Convert(pRootOfTree.right); if(right != null) { pRootOfTree.right = right; right.left = pRootOfTree; } return left != null ? left : pRootOfTree; }}
第二十七題:字串的排列
題目描述:
輸入一個字串,按字典序列印出該字串中字元的所有排列。例如輸入字串abc,則列印出由字元a,b,c所能排列出來的所有字串abc,acb,bac,bca,cab和cba。
輸入描述:
輸入一個字串,長度不超過9(可能有字元重複),字元只包括大小寫字母。
思路:
其實就是類比一個排列組合的過程,比如字串abc,先對0號位進行a,b,c三個字母的輪換,a是首位的情況下,b和c組合後輸出,即輸出abc,acb;然後b是首位的情況下,ac組合輸出。
所以很自然地就會發現整個過程需要用到交換函數,需要遞迴調用。
代碼:
import java.util.ArrayList;import java.util.Collections;public class Solution { public ArrayList<String> Permutation(String str) { ArrayList<String> ret = new ArrayList<String>(); if (str == null || str.length() == 0) { return ret; } permutation(ret, 0, str.toCharArray()); Collections.sort(ret); return ret; } public void permutation(ArrayList<String> retArrayList, int index, char[] s) { if (index == s.length - 1) { retArrayList.add(new String(s)); }else { for (int i = index; i < s.length; i++) { if (i == index || s[i] != s[index]) { swap(s, index, i); permutation(retArrayList, index+1, s); swap(s, index, i); } } } } public void swap(char[] s, int begin, int end) { char tmp = s[begin]; s[begin] = s[end]; s[end] = tmp; } }
第二十八題:數組中出現次數超過一半的數字
題目描述:
數組中有一個數字出現的次數超過數組長度的一半,請找出這個數字。例如輸入一個長度為9的數組{1,2,3,2,2,2,5,4,2}。由於數字2在數組中出現了5次,超過數組長度的一半,因此輸出2。如果不存在則輸出0。
思路:
由於這個數字出現的次數超過了一半,那麼我們可以掃描整個數組,得到 一個數字就記錄該數字,並記錄次數為1,當有出現該數字時次數加1,出現其他數字時,如果次數大於1則減1,否則換一個數字,並記錄該數字次數為1;當遍曆完整個數組後,如果此數組有一個數字次數大於一半那麼只有可能是最後得到的數字。
代碼:
public class Solution { public int MoreThanHalfNum_Solution(int [] array) { if (array == null || array.length == 0) { return 0; } if(array.length == 1) { return array[0]; } int tmp = array[0]; int count = 1; for (int i = 1; i<array.length; i++) { if(tmp == array[i]) { count ++; }else { if(count > 1){ count --; }else{ tmp = array[i]; count = 1; } } } if(!CheckMoreThanHalf(array, tmp)){ return 0; } return tmp; } public boolean CheckMoreThanHalf(int[] array, int tmp) { int count = 0; boolean ret = false; for (int i = 0; i < array.length; i++) { if (array[i] == tmp) { count ++; } } if(count*2 > array.length) { ret = true; } return ret; }}