經典題目:樹的遍歷及變種
輸入一顆二叉樹的跟節點和一個整數,打印出二叉樹中結點值的和爲輸入整數的所有路徑。路徑定義爲從樹的根結點開始往下一直到葉結點所經過的結點形成一條路徑。(注意: 在返回值的list中,數組長度大的數組靠前)。
遍歷方式:前、中、後 學習地址:https://www.cnblogs.com/vipchenwei/p/7562567.html
自己解決方式爲:
public class Solution {
ArrayList<ArrayList<Integer>> allList = new ArrayList<ArrayList<Integer>>();
ArrayList<Integer> list = new ArrayList<Integer>();
public ArrayList<ArrayList<Integer>> FindPath(TreeNode root,int target) {
if(root == null){
return allList;
}
list.add(root.val);
target -= root.val;
if(target == 0 && root.left == null && root.right == null){
allList.add(new ArrayList<Integer>(list));
}
FindPath(root.left,target);
FindPath(root.right,target);
//當往回遍歷時候,將路徑節點
list.remove(list.size() - 1);
return allList;
}
}
總結:基礎樹的操作,都是建立在樹的遍歷情況下,在遍歷情況下,進行一些操作。
經典題:字符串排序
輸入一個字符串,按字典序打印出該字符串中字符的所有排列。例如輸入字符串abc,則打印出由字符a,b,c所能排列出來的所有字符串abc,acb,bac,bca,cab和cba。
一般字符串題目比較簡單,但是一般會在簡單基礎上考慮人如何能做到資源的最大化利用。簡單的問題,往往是考察如何優化的功底
做法採用的是:固定前半段,進行交換。減少複雜度。
代碼
import java.util.*;
public class Solution {
public ArrayList<String> Permutation(String str) {
if(str == null){
return null;
}
ArrayList<String> list = new ArrayList<String>();
char[] cstr = str.toCharArray();
sort(cstr, 0 ,list);
Collections.sort(list);
return list;
}
public void sort(char[] str, int start ,ArrayList<String> list){
if(start == str.length - 1){
list.add(String.valueOf(str));
}
for(int i = start; i < str.length; i++){
if(i == start || str[i] != str[start]){
swap(str,i,start);
sort(str, start + 1 ,list);
swap(str,i,start);
}
}
}
public void swap(char[] A ,int i ,int j){
char temp = A[i];
A[i] = A[j];
A[j] = temp;
}
}
最小的K數:
輸入n個整數,找出其中最小的K個數。例如輸入4,5,1,6,2,7,3,8這8個數字,則最小的4個數字是1,2,3,4,。
方法很多常常用的有:採用排序算法、維護一個桶,桶是有序的,可以採用桶的形式。
動態規劃問題:簡單demo
HZ偶爾會拿些專業問題來忽悠那些非計算機專業的同學。今天測試組開完會後,他又發話了:在古老的一維模式識別中,常常需要計算連續子向量的最大和,當向量全爲正數的時候,問題很好解決。但是,如果向量中包含負數,是否應該包含某個負數,並期望旁邊的正數會彌補它呢?例如:{6,-3,-2,7,-15,1,2,2},連續子向量的最大和爲8(從第0個開始,到第3個爲止)。給一個數組,返回它的最大連續子序列的和,你會不會被他忽悠住?(子向量的長度至少是1)
思路很簡單 F(n) = f(n-1) + P F(n-1) > 0 否則是 F(N) = P
public class Solution {
public int FindGreatestSumOfSubArray(int[] array) {
if(array == null){
return 0;
}
int temp = 0;//以aaray[i]爲結尾的數
int sum = -999999999;//前i個數中最大的總和
for(int i = 0;i < array.length; i++){
temp = temp > 0?temp + array[i] : array[i];
sum = sum > temp?sum : temp;
}
return sum;
}
}
總結:動態規劃問題,都是採用f(n) 和F(N-1) 見關係問題。記住最基本模型,寫起來就有思路。並且要注意細節
字符串數字查找算法題:
題目:在一個字符串(0<=字符串長度<=10000,全部由字母組成)中找到第一個只出現一次的字符,並返回它的位置, 如果沒有則返回 -1(需要區分大小寫).
import java.util.*;
public class Solution {
public int FirstNotRepeatingChar(String str) {
Map<Character,Integer> m = new HashMap<Character,Integer>();
for(int i = 0; i < str.length() ;i++ ){
if(m.containsKey(str.charAt(i))){
m.put(str.charAt(i),m.get(str.charAt(i))+1);
}
else{
m.put(str.charAt(i),1);
}
}
for(int i = 0; i < str.length() - 1;i++){
if(m.get(str.charAt(i)) == 1){
return i ;
}
}
return -1;
}
}
通常思路是:遍歷一遍數據,將數據的字符串的次數打印出來。
也可以採用桶思想,字符串的桶的標識爲ASCLL。數字爲number 統計
還有就是堆排序好的進行查找。可以採用二分方法。
一般查詢考察二分查找。統計查找。面試時候一般總是考察變種能力。
總結:
1.樹的操作,基本上是在三種遍歷方式情況下的各種變種。在編寫代碼時候,一定要考慮各種邊界情況,和遞歸的向上返回和向下操作。
2.查找某類數據時候,主要考察堆各種排序算法的掌握情況。同時在面試或者寫代碼時候,總是會有優化空間。或者更加某些特殊的場景,可以做到空間與時間的轉化。一般查找問題,都會採用二分查找。
3.dp問題主要是分析好問題場景,分析出發fn 與fn-1情況下他們之間的關係。dp問題有時候和遞歸問題往往是可以相互轉化的。