算法專輯

回溯法

正則表達式匹配【分類討論思想】

origin link----回溯
dim—dp

  1. 有 * 【首字符匹配(*匹配多個)||首字符不匹配(*匹配0個)】,無 *【首字符匹配&&後續都要匹配】
  2. 程序終結的條件:【模式串爲空,匹配串不爲空,結果:fasle】,【模式串爲空,匹配串爲空,結果:true】
  3. 不斷縮小字符串,重複執行以上步驟。
public boolean isMatch(String s, String p){
        if (p.isEmpty()) return s.isEmpty();
        boolean firstMatch=(!s.isEmpty()&&(s.charAt(0)==p.charAt(0)||p.charAt(0)=='.'));
        if (p.length()>1&&p.charAt(1)=='*'){
            return   (firstMatch&&isMatch(s.substring(1),p))||isMatch(s,p.substring(2));
        }else {
            return firstMatch&&isMatch(s.substring(1),p.substring(1));
        }
    }

分割數組的最大值【用棧分析代碼遞歸的執行過程】

排列組合問題【最通用的解題思路】

origin link
在這裏插入圖片描述

  • 比如給你數組[1,2,3],輸出該數組所有可能的全排列
public class Solution {
    boolean[] isused=new boolean[100];
    List<Integer>templist=new ArrayList<>();
    List<List<Integer>>rst=new ArrayList<>();
    public static void main(String[] args) {
        int[] a=new int[]{1,2,3};
        List<List<Integer>> an=new Solution().arrange(a,0);
        System.out.println(an);
    }
    public List<List<Integer>> arrange(int[] nums,int index) {
        if (index==nums.length) {rst.add(new ArrayList<>(templist));}
        // //這裏會遍歷nums.length*nums.length次
        for (int i = 0; i <nums.length ; i++) {
            if(!isused[i]){
                isused[i]=true;
                templist.add(nums[i]);
                arrange(nums,index+1);
                templist.remove(templist.size()-1);
                isused[i]=false;
            }
        }
        return rst;
    }
}

對12345進行全排列

0{
   0[
      1,{0~4},2,{0~4},3,{4},4
   ]
   
   1[
      0{0~4},1,2,{0~4},2,{0~4},3,{0~4},4{0~4}
   ]
   
   2[
      0,{0~4},1,{0~4}.......
   ]
}

解釋說明:	01{0~4}對應012013014即【12312412502{0~4}對應【13213413503{4}對應【145
  • 組合
/**
 * 從1,2,3,4,5中選擇3個數,求所有的組合
 */
public class Combination {
   static List<List<Integer>>res=new ArrayList<>();
   static List<Integer>list=new ArrayList<Integer>();
    public static void main(String[] args) {
        Combination combination = new Combination();
        combination.combination(new int[]{1,2,3,4,5},3,0);
        System.out.println(res);
        System.out.println(res.size());
    }
    /**
     * 在下一次循環開始之前,直接跳過下次循環,然後回溯狀態,接着循環下去。
     * 在循環中,[int i = h/i=0;這條語句在每次遞歸再次進入循環時都會得到執行]
     * 【即for(int i = h/i=0; i <n;i++)】,每當滿足條件,就跳過一次循環(拿來用作狀態回退),
     */
     void combination(int[] nums, int k, int h) {
        if (list.size()==k){res.add(new ArrayList<>(list));return;}
         /**
          * 通過終止條件,進行剪枝優化,避免無效的遞歸
          *         c中還剩 k - c.size()個空位,所以[ i ... n]中至少要有k-c.size()個元素
          *         所以i最多爲 n - (k - c.size()) + 1
          *         i <= n - (k - c.size()) + 1;
          */
        for (int i = h; i <nums.length ; i++) {
            list.add(nums[i]);
            /**
             *這裏是i+1,不是h+1,否則會出現i=2,h=1,那麼結果中會有【1,3,3】
             * 當125添加後。i=nums.length,此時for結束,combination(nums,k,h+1,list);
             * 即h+1少了一次執行機會,i就提前比h多加了一個1,i和h就從這裏開始不同步了
             */
            combination(nums,k,i+1);
            list.remove(list.size()-1);
        }
    }
}

二進制中1的個數【數字/位運算–與運算】

輸入一個整數,輸出該數二進制表示中1的個數。其中負數用補碼錶示。

public class Solution {
    public static void main(String[] args) {
        int a=new Solution().NumberOf1(2);
        System.out.println(a);
    }
    public int NumberOf1(int n) {
        int count=0;
        while(n!=0){
            n=n&(n-1);
            count++;
        }
        return count;
    }
}

重建二叉樹(給出前序中序)【遞歸】

/**
 * 重建二叉樹(給出前序中序)【遞歸】
 *
 * 輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。
 * 假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。
 * 例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6},
 * 則重建二叉樹並返回。
 */
public class Main {
    public static void main(String[] args) {
        int[] a=new int[]{1,2,3,4,5};
        int[] b=new int[]{3,2,4,1,5};
        Main main = new Main();
        TreeNode treeNode=main.reConstructBinaryTree(a,b);
        System.out.println(treeNode);
    }
    public TreeNode reConstructBinaryTree(int [] pre, int [] in) {
        if(pre.length==0||in.length==0) return null;
        TreeNode treeNodes=new TreeNode(pre[0]);
        for (int i = 0; i <in.length ; i++) {
            if (in[i]==pre[0]){
                treeNodes.left=reConstructBinaryTree(Arrays.copyOfRange(pre,1,i+1),Arrays.copyOfRange(in,0,i));
                treeNodes.right=reConstructBinaryTree(Arrays.copyOfRange(pre,i+1,pre.length),Arrays.copyOfRange(in,i+1,in.length));
                break;
            }
        }
        return treeNodes;
    }
}

不重複子字符串的最大長度

lengthOfLongestSubstring


堆排序【堆(優先隊列)】

這其實就是PriotyQueue優先隊列的代碼實現。

半堆化:一顆二叉樹,先將值最大的數交換到根節點,然後對於被交換的節點(沒有被交換的節點,就直接遞歸結束),再使用同樣的(遞歸)方法,進行交換,直到空節點。遞歸結束。(他只能保證二叉樹的一個分叉,符合大頂堆)

完全堆化:從完全二叉樹的最後一個根節點開始,逆向遍歷。每輪循環都進行一次半堆化。

public class HeapSort {
    public static void main(String[] args) {
        int[] tree = {5, 2, 7, 3, 6, 1, 40};
        heapsort(tree);
    }
    static void heapsort(int[] tree){
        for (int i = (tree.length - 2) / 2; i >= 0; i--) {
            heapify(tree, tree.length, i);
        }
        for (int i = tree.length - 1; i >= 0; i--) {
            swap(tree, i, 0);
            heapify(tree, i, 0);
        }
        for (int j : tree) System.out.println(j);
    }
    static void heapify(int[] tree, int n, int index){
        if(index>=n) return;
        int maxIndex=index;
        if(2*index+1<n&&tree[maxIndex]<tree[2*index+1]) maxIndex=2*index+1;
        if(2*index+2<n&&tree[maxIndex]<tree[2*index+2]) maxIndex=2*index+2;  //找到值最大的元素的下標
        if(maxIndex!=index) {swap(tree,maxIndex,index);heapify(tree,n,maxIndex);} //調整被交換的節點爲根的二叉樹【半堆化】
    }
    static void swap(int[] tree, int maxIndex, int i) {
        int temp=tree[maxIndex];
        tree[maxIndex]=tree[i];
        tree[i]=temp;
    }
}

二叉樹前中後遍歷&BFS遍歷&DFS遍歷

origin link

更多

斐波那契數列【遞歸/dp】

寫一個函數,輸入 n ,求斐波那契(Fibonacci)數列的第 n 項。斐波那契數列的定義如下:
F(0) = 0
F(1) = 1
F(N) = F(N - 1) + F(N - 2), 其中 N > 1.

遞歸實現

public class Main {
    public static void main(String[] args) {
        Main main = new Main();
        System.out.println(main.Fibonacci(3));
    }
    public int Fibonacci(int n) {
        if (n==0) return 0;
        else if(n==1) return 1;
        else {
           return Fibonacci(n-1)+Fibonacci(n-2);
        }
    }
}

dp實現

 public int FibonacciDP(int n){
        int dp[]=new int[n+1];
        dp[0]=0;
        dp[1]=1;
        for (int i = 2; i <=n ; i++) {
            dp[i]=dp[i-1]+dp[i-2];
        }
        return dp[n];
    }

dim

輸入n=5,s=4
輸出
[2,1,1,1]
[1,2,1,1]
[1,1,2,1]
[1,1,1,2]
解釋 2+1+1+1=5

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章