1. 程式人生 > 其它 >acwing 基礎演算法班 java實現

acwing 基礎演算法班 java實現

第一講 基礎演算法

快速排序

AcWing 785. 快速排序
package com.acwing;

import java.util.*;

public class ac785 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] nums = new int[n];
        for (int i = 0; i < n; i++) nums[i] = sc.nextInt();
        sortQuick(nums, 0, n - 1);
        for (int x : nums) System.out.print(x + " ");
    }

    public static void sortQuick(int[] nums, int l, int r) {
        if (l >= r) return;
        int x = nums[l], i = l - 1, j = r + 1;
        while (i < j) {
            while (nums[++i] < x) ;
            while (nums[--j] > x) ;
            if (i < j) {
                int temp = nums[i];
                nums[i] = nums[j];
                nums[j] = temp;
            }
        }
        sortQuick(nums, l, j);
        sortQuick(nums, j + 1, r);
    }
}
AcWing 786. 第k個數
import java.util.*;

public class ac786 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int k = sc.nextInt();
        int[] nums = new int[n];
        for (int i = 0; i < n; i++) nums[i] = sc.nextInt();
        int out = sortQuick(nums, 0, n - 1, k);
        System.out.println(out);
    }

    public static int sortQuick(int[] nums, int l, int r, int k) {
        if (l == r) return nums[l];
        int x = nums[l], i = l - 1, j = r + 1;
        while (i < j) {
            while (nums[++i] < x) ;
            while (nums[--j] > x) ;
            if (i < j) {
                int temp = nums[i];
                nums[i] = nums[j];
                nums[j] = temp;
            }
        }
        int sl = j - l + 1;
        if (k <= sl) return sortQuick(nums, l, j, k);
        else return sortQuick(nums, j + 1, r, k - sl);
    }
}

歸併排序

AcWing 787. 歸併排序
import java.util.Scanner;

public class ac787 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] nums = new int[n];
        for (int i = 0; i < n; i++) nums[i] = sc.nextInt();
        merge_sort(nums, 0, n - 1);
        for (int x : nums) System.out.print(x + " ");
    }

    public static void merge_sort(int[] nums, int l, int r) {
        if (l >= r) return;
        int mid = (l + r) >> 1;
        merge_sort(nums, l, mid);
        merge_sort(nums, mid + 1, r);
        int index = 0, i = l, j = mid + 1;
        int[] temp = new int[r - l + 1];
        while (i <= mid && j <= r) {
            if (nums[i] <= nums[j]) temp[index++] = nums[i++];
            else temp[index++] = nums[j++];
        }
        while (i <= mid) temp[index++] = nums[i++];
        while (j <= r) temp[index++] = nums[j++];
        for (i = l, j = 0; i <= r; i++, j++) nums[i] = temp[j];
    }
}
AcWing 788. 逆序對的數量
package com.acwing;


import java.util.Scanner;

public class ac788 {
    static int count = 0;

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] nums = new int[n];
        for (int i = 0; i < n; i++) nums[i] = sc.nextInt();
        System.out.println(merge_sort(nums, 0, n - 1));
    }

    public static long merge_sort(int[] nums, int l, int r) {
        if (l >= r) return 0;
        int mid = (l + r) >> 1;
        long res = merge_sort(nums, l, mid) + merge_sort(nums, mid + 1, r);

        int index = 0, i = l, j = mid + 1;
        int[] temp = new int[r - l + 1];
        while (i <= mid && j <= r) {
            if (nums[i] <= nums[j]) temp[index++] = nums[i++];
            else {
                temp[index++] = nums[j++];
                res+=mid-i+1;
            }
        }
        while (i <= mid) temp[index++] = nums[i++];
        while (j <= r) temp[index++] = nums[j++];
        for (i = l, j = 0; i <= r; i++, j++) nums[i] = temp[j];
        return res;
    }
}

二分

模板1: 區間 [l,r] 劃分為 [l,mid] 和 [mid+1,r] 時使用

int besearch_1(int l,int r){
    while(l<r){
        int mid=l+r>>1;
        if(check(mid)) r=mid;
        else l=mid+1
    }
    return l;
}

模板2: 區間 [l,r] 劃分為 [l,mid-1] 和 [mid,r] 時使用

int besearch_2(int l,int r){
    while(l<r){
        int mid=l+r+1>>1;
        if(chech(mid)) l=mid;
        else r=mid-1;
    }
    return l;
}
AcWing 789. 數的範圍

import java.util.Scanner;

public class ac789 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        int[] nums = new int[n];
        for (int i = 0; i < n; i++) nums[i] = sc.nextInt();
        while (m-- > 0) {
            int target = sc.nextInt();
            int left = get_left(nums, target);
            if (nums[left] != target) {
                System.out.println("-1 -1");
                continue;
            }
            int right = get_right(nums, target);
            System.out.println(left + " " + right);
        }
    }

    public static int get_left(int[] nums, int target) {
        int left = 0, right = nums.length - 1;
        while (left < right) {
            int mid = left + right >> 1;
            if (nums[mid] >= target) {
                right = mid;
            } else left = mid + 1;
        }
        return right;
    }

    public static int get_right(int[] nums, int target) {
        int left = 0, right = nums.length - 1;
        while (left < right) {
            int mid = left + right + 1 >> 1;
            if (nums[mid] <= target) {
                left = mid;
            } else right = mid - 1;
        }
        return left;
    }
}
AcWing 790. 數的三次方根
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        double x=sc.nextDouble();
        double l=-10000,r=10000;
        while (r-l>1e-8){
            double mid=(l+r)/2;
            if(mid*mid*mid>=x) r=mid;
            else l=mid;
        }
        System.out.println(String.format("%.6f", l));
    }
}

字首和與差分

AcWing 795. 字首和
import java.util.Scanner;

public class lc795 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        int[] nums = new int[n+1];
        int[] table = new int[n + 1];
        for (int i = 1; i <= n; i++) {
            nums[i] = sc.nextInt();
            table[i] = table[i-1] + nums[i];
        }
        while (m-- > 0) {
            int l = sc.nextInt();
            int r = sc.nextInt();
            System.out.println(table[r] - table[l-1]);
        }
    }
}
AcWing 796. 子矩陣的和
import java.util.Scanner;

public class ac796 {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int n= sc.nextInt();
        int m=sc.nextInt();
        int q=sc.nextInt();
        int[][] table=new int[n+1][m+1];
        int[][] dp=new int[n+1][m+1];
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                table[i][j]=sc.nextInt();
                dp[i][j]=dp[i-1][j]+dp[i][j-1]+table[i][j]-dp[i-1][j-1];
            }
        }
        while (q-->0){
            int x1=sc.nextInt();
            int y1=sc.nextInt();
            int x2=sc.nextInt();
            int y2=sc.nextInt();
            System.out.println(dp[x2][y2]-dp[x1-1][y2]-dp[x2][y1-1]+dp[x1-1][y1-1]);
        }
    }
}
AcWing 797. 差分
import java.util.Scanner;

public class ac797 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m=sc.nextInt();
        int[] nums = new int[n + 1];
        int[] table = new int[n + 2];
        for (int i = 1; i <= n; i++) {
            nums[i] = sc.nextInt();
            table[i] += nums[i];
            table[i + 1] -= nums[i];
        }
//        for (int x : nums) System.out.print(x + "\t");
//        System.out.println();
//        for (int x : table) System.out.print(x + "\t");
//        System.out.println();
        while (m-->0){
            int l=sc.nextInt();
            int r=sc.nextInt();
            int c=sc.nextInt();
            table[l]+=c;
            table[r+1]-=c;
        }
        for(int i=1;i<=n;i++){
            table[i]+=table[i-1];
            System.out.print(table[i]+" ");
        }

    }
}
AcWing 798. 差分矩陣
package com.acwing;

import java.util.Scanner;

public class ac798 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        int q = sc.nextInt();
        int[][] nums = new int[n + 1][m + 1];
        int[][] dp = new int[n + 2][m + 2];
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                nums[i][j] = sc.nextInt();
                insert(dp,i,j,i,j,nums[i][j]);
            }
        }
        while (q-->0){
            int x1=sc.nextInt();
            int y1=sc.nextInt();
            int x2=sc.nextInt();
            int y2=sc.nextInt();
            int c=sc.nextInt();
            insert(dp,x1,y1,x2,y2,c);
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                dp[i][j]+=dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1];
                System.out.print(dp[i][j]+" ");
            }
            System.out.println();
        }
    }

    public static void insert(int[][] dp, int x1, int y1, int x2, int y2, int c) {
        dp[x1][y1] += c;
        dp[x2 + 1][y1] -= c;
        dp[x1][y2 + 1] -= c;
        dp[x2+1][y2+1] += c;
    }
}

雙指標

AcWing 799. 最長連續不重複子序列
import java.util.*;

public class ac799 {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        int[] nums=new int[n];
        for(int i=0;i<n;i++) nums[i]=sc.nextInt();
        int left=0;
        HashMap<Integer,Integer> map=new HashMap();
        int max=Integer.MIN_VALUE;
        for(int i=0;i<n;i++){
            if(map.containsKey(nums[i])){
                left=Math.max(left,map.get(nums[i])+1);
            }
            map.put(nums[i],i);
            max=Math.max(max,i-left+1);
        }
        System.out.println(max);
    }
}
AcWing 800. 陣列元素的目標和
package com.acwing;

import java.util.Scanner;

public class ac800 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        int x = sc.nextInt();
        int[] a = new int[n];
        int[] b = new int[m];
        for (int i = 0; i < n; i++) a[i] = sc.nextInt();
        for (int i = 0; i < m; i++) b[i] = sc.nextInt();
        int i = 0, j = m-1;
        while (i < n && j >=0) {
            if(a[i]+b[j]==x) break;
            else if(a[i]+b[j]>x) j--;
            else i++;
        }
        System.out.println(i+" "+j);
    }
}
AcWing 2816. 判斷子序列
import java.util.Scanner;

public class ac2816 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        int[] a = new int[n];
        int[] b = new int[m];
        for (int i = 0; i < n; i++) a[i] = sc.nextInt();
        for (int j = 0; j < m; j++) b[j] = sc.nextInt();
        int i=0,j=0;
        while (i<n&&j<m){
            if(a[i]==b[j])i++;
            j++;
        }
        if(i==n) System.out.println("Yes");
        else System.out.println("No");
    }
}

位運算

AcWing 801. 二進位制中1的個數
import java.util.Scanner;

public class ac801 {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        while (n-->0){
            int x=sc.nextInt();
            int count=0;
            while (x!=0){
                if((x&1)==1) count++;
                x=x>>1;
            }
            System.out.print(count+" ");
        }
    }
}

離散化

AcWing 802. 區間和
package com.acwing;

import java.util.*;

public class ac802 {

    static TreeSet<Integer> set=new TreeSet<>();
    static List<Integer> alls=new ArrayList<>();
    static List<int[]> adds=new ArrayList<>();
    static List<int[]> query=new ArrayList<>();
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        int m=sc.nextInt();
        for(int i=0;i<n;i++){
            int x=sc.nextInt();
            int c=sc.nextInt();
            adds.add(new int[]{x,c});
            set.add(x);
        }
        for(int i=0;i<m;i++){
            int l=sc.nextInt();
            int r=sc.nextInt();
            query.add(new int[]{l,r});
            set.add(l);
            set.add(r);
        }
        for(int x:set) alls.add(x);
        Collections.sort(alls);
        for(int x:alls) System.out.print(x+" ");
        int[] a=new int[alls.size()+1];
        int[] s=new int[alls.size()+1];
        for(int[] add:adds){
            int x=find(add[0]);
            a[x]+=add[1];
        }
        for(int i=1;i<a.length;i++){
            s[i]=s[i-1]+a[i];
        }
        for(int[] que:query){
            int l=find(que[0]);
            int r=find(que[1]);
            System.out.println(s[r]-s[l-1]);
        }
    }

    public static int find(int x){
        int l=0,r=alls.size()-1;
        while (l<r){
            int mid=l+r>>1;
            if(alls.get(mid)>=x) r=mid;
            else l=mid+1;
        }
        return r+1;
    }
}

區間合併

AcWing 803. 區間合併
package com.acwing;

import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;

public class ac803 {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        int[][] a=new int[n][2];
        for(int i=0;i<n;i++){
            a[i][0]=sc.nextInt();
            a[i][1]=sc.nextInt();
        }
        Arrays.sort(a,(Comparator.comparingInt(o -> o[0])));
        int ed=Integer.MIN_VALUE;
        int count=0;
        for(int[] x:a){
            System.out.println(x[0]+" "+x[1]);
            if(ed<x[0]){
                ed=x[1];
                count++;
            }else {
                ed=Math.max(ed,x[1]);
            }
        }
        System.out.println(count);
    }
}

第二講 資料結構

單鏈表

AcWing 826. 陣列模擬單鏈表
import java.util.List;
import java.util.Scanner;

public class ac826 {

    static int N=100010;
    static int head,idx;
    static int[] e=new int[N];
    static int[] ne=new int[N];

    public static void init(){
        head=-1;
        idx=0;
    }
    public static void add_head(int x){
        e[idx]=x;
        ne[idx]=head;
        head=idx;
        idx++;
    }
    public static void add(int k,int x){
        e[idx]=x;
        ne[idx]=ne[k];
        ne[k]=idx;
        idx++;
    }
    public static void remove(int k) {
        ne[k]=ne[ne[k]];
    }

    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        init();
        while (n-->0){
            char c=sc.next().charAt(0);
            if(c=='H'){
                int x=sc.nextInt();
                add_head(x);
            }
            else if(c=='D'){
                int k=sc.nextInt();
                if(k==0) head=ne[head];
                else remove(k-1);
            }
            else if(c=='I'){
                int k=sc.nextInt();
                int x=sc.nextInt();
                add(k-1,x);
            }
        }
        for(int i=head;i!=-1;i=ne[i]){
            System.out.print(e[i]+" ");
        }
    }
}
AcWing 827. 陣列模擬雙鏈表

棧和佇列

AcWing 828. 陣列模擬棧
package com.acwing;

import java.util.Scanner;

public class ac828 {

//    push x – 向棧頂插入一個數 x;
//    pop – 從棧頂彈出一個數;
//    empty – 判斷棧是否為空;
//    query – 查詢棧頂元素
    static int N=100010;
    static int[] stk=new int[N];
    static int tt=0;
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        while (n-->0){
            String op=sc.next();
            if(op.equals("push")){
                int x=sc.nextInt();
                stk[tt++]=x;
            }else if(op.equals("pop")){
                tt--;
            }else if(op.equals("query")){
                System.out.println(stk[tt-1]);
            }else if(op.equals("empty")){

                if(tt>0) System.out.println("NO");
                else System.out.println("YES");
            }
        }
    }

}
AcWing 3302. 表示式求值
import java.util.*;

public class ac3302 {
    static Stack<Character> op = new Stack<>();
    static Stack<Integer> num = new Stack<>();
    static HashMap<Character, Integer> map = new HashMap<>();
    public static void main(String[] args) {
        map.put('+', 1);
        map.put('-', 1);
        map.put('*', 2);
        map.put('/', 2);
        char[] str = new Scanner(System.in).next().toCharArray();
        for (int i = 0; i < str.length; i++) {
            char c = str[i];
            if (Character.isDigit(c)) {
                int x = 0, j = i;
                while (j < str.length && Character.isDigit(str[j])) {
                    x = x * 10 + str[j++] - '0';

                }
                i=j-1;
                num.push(x);
            }
            else if (c == '(') op.push(c);
            else if (c == ')') {
                while (op.peek() != '(') eval();
                op.pop();
            }
            else {
                while (!op.isEmpty()&&op.peek()!='(' && map.get(op.peek()) >= map.get(c)) eval();
                op.push(c);
            }
        }
        while (op.size() > 0) eval();
        System.out.println(num.peek());
    }
    public static void eval() {
        int b = num.pop();
        int a = num.pop();
        char c = op.pop();
        int x;
        if (c == '+') x = a + b;
        else if (c == '-') x = a - b;
        else if (c == '*') x = a * b;
        else x = a / b;
        num.push(x);
    }
}
AcWing 829. 模擬佇列
package com.acwing;

import java.util.Scanner;

public class ac829 {
    static int N=1000010;
    static int[] que=new int[N];
    static int hh=0,tt=-1;

    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        while (n-->0){
            String s=sc.next();
            if(s.equals("push")){
                int x=sc.nextInt();
                que[++tt]=x;
            }else if(s.equals("empty")){
                if(hh>tt) System.out.println("YES");
                else System.out.println("NO");;
            }else if(s.equals("pop")){
                hh++;
            }else if(s.equals("query")){
                System.out.println(que[hh]);
            }
        }
    }
}
AcWing 830. 單調棧
import java.util.Scanner;
import java.util.Stack;

public class ac830 {
    public static void main(String[] args) {
        Stack<Integer> stk=new Stack<>();
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        for(int i=0;i<n;i++){
            int x=sc.nextInt();
            if(i==0){
                stk.push(x);
                System.out.print(-1+" ");
            }else {
                while (!stk.isEmpty()&&stk.peek()>=x){
                    stk.pop();
                }
                if(stk.isEmpty()) System.out.print(-1+" ");
                else System.out.print(stk.peek()+" ");
                stk.push(x);
            }
        }
    }
}
AcWing 154. 滑動視窗 && 單調佇列
import java.util.*;

public class ac154 {

    static int N = 10000010;
    static int[] a = new int[N];
    static int[] q = new int[N];

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int k = sc.nextInt();
        for (int i = 0; i < n; i++) a[i] = sc.nextInt();
        int hh = 0, tt = -1;
        for (int i = 0; i < n; i++) {
            if (hh <= tt && q[hh] < i - k + 1) hh++;
            while (hh <= tt && a[q[tt]] >= a[i]) tt--;
            q[++tt] = i;
            if(i>=k-1) System.out.print(a[q[hh]]+" ");
        }
        System.out.println();
        hh=0;
        tt=-1;
        for(int i=0;i<n;i++){
            if(hh<=tt&&q[hh]<i-k+1) hh++;
            while (hh<=tt&&a[q[tt]]<=a[i]) tt--;
            q[++tt]=i;
            if(i>=k-1) System.out.print(a[q[hh]]+" ");
        }
    }
}

Trie

AcWing 835. Trie字串統計
import java.util.Scanner;

public class ac835 {
    static int N = 100010;
    static int[][] son = new int[N][26];
    static int[] cnt = new int[N];
    static char[] str;
    static int idx = 0;

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        while (n-- > 0) {
            char c = sc.next().charAt(0);
            str = sc.next().toCharArray();
            if (c == 'I') insert(str);
            else System.out.println(query(str));
        }
    }

    public static void insert(char[] str) {
        int p = 0;
        for (int i = 0; i < str.length; i++) {
            int u = str[i] - 'a';
            if (son[p][u] == 0) son[p][u] = ++idx;
            p = son[p][u];
        }
        cnt[p]++;
    }

    public static int query(char[] str) {
        int p = 0;
        for (int i = 0; i < str.length; i++) {
            int u = str[i] - 'a';
            if (son[p][u] == 0) return 0;
            p = son[p][u];
        }
        return cnt[p];
    }
}
AcWing 143. 最大異或對

並查集

AcWing 836. 合併集合
import java.util.Scanner;

public class ac836 {
    static int N = 100010;
    static int[] p = new int[N];
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        for (int i = 0; i <= n; i++) p[i] = i;
        while (m-- > 0) {
            char c = sc.next().charAt(0);
            int a = sc.nextInt();
            int b = sc.nextInt();
            if(c=='M'){
                p[find(a)]=find(b);
            }else {
                if(find(a)==find(b)) System.out.println("Yes");
                else System.out.println("No");
            }
        }
    }
    public static int find(int x) {
        if (p[x] != x) p[x] = find(p[x]);
        return p[x];
    }
}
AcWing 837. 連通塊中點的數量
import java.util.Scanner;

public class ac837 {
    static int N=100010;
    static int[] p=new int[N];
    static int[] size=new int[N];

    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        int m=sc.nextInt();
        for(int i=0;i<n;i++){
            p[i]=i;
            size[i]=1;
        }
        while (m-->0){
            String s=sc.next();
            if(s.equals("C")){
                int a=sc.nextInt();
                int b=sc.nextInt();
                if(find(a)==find(b)) continue;
                size[find(b)]+=size[find(a)];
                p[find(a)]=find(b);

            }else if(s.equals("Q1")){
                int a=sc.nextInt();
                int b=sc.nextInt();
                if(find(a)==find(b)) System.out.println("Yes");
                else System.out.println("No");
            }else {
                int a=sc.nextInt();
                System.out.println(size[find(a)]);
            }
        }
    }

    public static int find(int x){
        if(p[x]!=x) p[x]=find(p[x]);
        return p[x];
    }
}
AcWing 240. 食物鏈
import java.util.Scanner;

public class ac240 {

    static int N = 50010;
    static int[] p = new int[N];
    static int[] d = new int[N];

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        for (int i = 0; i < n; i++) p[i] = i;
        int ans = 0;
        while (m-- > 0) {
            int t = sc.nextInt();
            int x = sc.nextInt();
            int y = sc.nextInt();
            if(x>n||y>n) ans++;
            else {
                int px=find(x),py=find(y);
                if(t==1){
                    if(px==py&&(d[x]-d[y])%3!=0) ans++;
                    else if(px!=py){
                        p[px]=py;
                        d[px]=d[y]-d[x];
                    }
                }else {
                    if(px==py&&(d[x]-d[y]-1)%3!=0) ans++;
                    else if(px!=py){
                        p[px]=py;
                        d[px]=d[y]+1-d[x];
                    }
                }
            }
        }
        System.out.println(ans);
    }

    public static int find(int x) {
        if (p[x] != x) {

            int t = find(p[x]);
            d[x] += d[p[x]];
            p[x]=t;
        }
        return p[x];
    }
}

AcWing 838. 堆排序
import java.util.PriorityQueue;
import java.util.Scanner;

public class ac838 {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        int m=sc.nextInt();
        PriorityQueue<Integer> que=new PriorityQueue<>();
        while (n-->0){
            int x=sc.nextInt();
            que.offer(x);
        }
        while (!que.isEmpty()&&m>0){
            System.out.print(que.poll()+" ");
            m--;
        }
    }
}

第三章 搜尋與圖論

DFS

AcWing 842. 排列數字
import java.util.*;

public class ac842 {
    static List<List<Integer>> ans = new ArrayList<>();
    static List<Integer> temp = new ArrayList<>();

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        boolean[] used = new boolean[n];
        dfs(n, used);
        for (List<Integer> res : ans) {
            for (int x : res) System.out.print(x + " ");
            System.out.println();
        }
    }

    public static void dfs(int n, boolean[] used) {
        if (temp.size() == n) {
            ans.add(new ArrayList<>(temp));
            return;
        }
        for (int i = 0; i < n; i++) {
            if (!used[i]) {
                used[i] = true;
                temp.add(i + 1);
                dfs(n, used);
                temp.remove(temp.size() - 1);
                used[i] = false;
            }
        }
    }
}
AcWing 843. n-皇后問題
package com.acwing;

import java.util.Arrays;
import java.util.Scanner;

public class ac843 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        char[][] chess = new char[n][n];
        for (char[] ch : chess) Arrays.fill(ch, '.');
        dfs(chess, 0);
    }

    public static void dfs(char[][] chess, int index) {
        if (index == chess.length) {
            print_chess(chess);
        }
        for (int j = 0; j < chess.length; j++) {
            if (valid(chess, index, j)) {
                chess[index][j] = 'Q';
                dfs(chess, index + 1);
                chess[index][j] = '.';
            }
        }
    }
 
    public static void print_chess(char[][] chess) {
        for (char[] ch : chess) {
            for (char c : ch) System.out.print(c);
            System.out.println();
        }
        System.out.println();
    }

    public static boolean valid(char[][] chess, int x, int y) {
        for (int i = 0; i < x; i++) if (chess[i][y] == 'Q') return false;
        for (int i = x, j = y; i >= 0 && j >= 0; i--, j--) if (chess[i][j] == 'Q') return false;
        for (int i = x, j = y; i >=0 && j <chess.length; i--, j++) if (chess[i][j] == 'Q') return false;
        return true;
    }
}

BFS

AcWing 844. 走迷宮
package com.acwing;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

public class ac844 {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        int[][] a = new int[n][m];
        int[][] b = new int[n][m];
        for (int[] bb : b) Arrays.fill(bb, -1);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                a[i][j] = sc.nextInt();
            }
        }
        boolean[][] used = new boolean[n][m];
        Queue<int[]> que = new LinkedList<>();
        que.offer(new int[]{0, 0});
        b[0][0] = 0;
        while (!que.isEmpty()) {
            int size = que.size();
            for (int p = 0; p < size; p++) {
                int[] pos = que.poll();
                int x = pos[0];
                int y = pos[1];
                used[x][y] = true;
                int[] dx = {1, -1, 0, 0,};
                int[] dy = {0, 0, 1, -1};
                for (int k = 0; k < 4; k++) {
                    int new_x = x + dx[k];
                    int new_y = y + dy[k];
                    if (new_x >= 0 && new_x < n && new_y >= 0 && new_y < m && a[new_x][new_y] != 1 && b[new_x][new_y] == -1) {
                        b[new_x][new_y] = b[x][y] + 1;
                        que.offer(new int[]{new_x, new_y});
                    }
                }
            }
        }
        System.out.println(b[n - 1][m - 1]);
    }
}

樹與圖的深度優先遍歷

AcWing 846. 樹的重心
import java.util.*;

public class ac846 {

    static HashMap<Integer, List<Integer>> tree = new HashMap<>();
    static int ans=Integer.MAX_VALUE;
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);


        int n = sc.nextInt();
        boolean[] used=new boolean[n+1];

        for (int i = 0; i < n - 1; i++) {
            int a = sc.nextInt(), b = sc.nextInt();
            insert(a, b);
            insert(b, a);
        }
//        for(int k:tree.keySet()){
//            System.out.print(k+" :");
//            List<Integer> t=tree.get(k);
//            for(int x:t) System.out.print(x+" ");
//            System.out.println();
//        }
        dfs(1,n,used);
        System.out.println(ans);
    }

    public static void insert(int x, int y) {
        List<Integer> temp = tree.getOrDefault(x, new ArrayList<>());
        temp.add(y);
        tree.put(x, temp);
    }
    public static int dfs(int root,int n,boolean[] used){
        used[root]=true;
        List<Integer> temp=tree.get(root);
        if(temp==null) return 1;
        int count=1;
        int res=0;
        for(int x: temp){
            if(!used[x]){
                int child=dfs(x,n,used);
                res=Math.max(res,child);
                count+=child;
            }
        }
        res=Math.max(res,n-count);
        ans=Math.min(ans,res);
        return count;
    }

}

樹與圖的廣度優先遍歷

AcWing 847. 圖中點的層次
import java.util.*;

public class ac847 {
    static HashMap<Integer, List<Integer>> map = new HashMap<>();

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        boolean[] used = new boolean[n + 1];
        for (int i = 0; i < m; i++) {
            int a = sc.nextInt();
            int b = sc.nextInt();
            insert(a, b);
            insert(b, a);
        }
        Queue<Integer> que = new LinkedList<>();
        que.offer(1);
        int count = 0;
        boolean flag = false;

//        for (int k : map.keySet()) {
//            System.out.print(k + " :");
//            List<Integer> t = map.get(k);
//            for (int x : t) System.out.print(x + " ");
//            System.out.println();
//        }
//        System.out.println("----------");

        while (!que.isEmpty()) {
            int size = que.size();
            List<Integer> next=new ArrayList<>();
            for (int i = 0; i < size; i++) {
                int x = que.poll();
                if(x==n) flag=true;
                used[x] = true;
                List<Integer> temp = map.getOrDefault(x,new ArrayList<>());
                for (int y : temp) next.add(y);
            }
            if (flag) break;
            for(int x:next) if(!used[x]) que.offer(x);
            //System.out.println();
            count++;
        }
        if(flag==false) System.out.println(-1);
        else System.out.println(count);
    }

    public static void insert(int x, int y) {
        List<Integer> temp = map.getOrDefault(x, new ArrayList<>());
        temp.add(y);
        map.put(x, temp);
    }
}

拓撲排序

AcWing 848. 有向圖的拓撲序列
import java.util.*;

public class ac848 {
    static HashMap<Integer, List<Integer>> map = new HashMap<>();

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        int[] iner = new int[n + 1];
        while (m-- > 0) {
            int a = sc.nextInt();
            int b = sc.nextInt();
            iner[b]++;
            List<Integer> temp = map.getOrDefault(a, new ArrayList<>());
            temp.add(b);
            map.put(a, temp);
        }
        Queue<Integer> que = new LinkedList<>();
        List<Integer> ans = new ArrayList<>();
        boolean[] used = new boolean[n + 1];
        boolean flag = false;
        for (int i = 1; i <= n; i++) if (iner[i] == 0) que.offer(i);

        while (!que.isEmpty()) {
            int size=que.size();
            List<Integer> temp=new ArrayList<>();
            for(int i=0;i<size;i++){
                int x=que.poll();
                used[x]=true;
                ans.add(x);
                System.out.print(x+" ");
                List<Integer> next=map.getOrDefault(x,new ArrayList<>());
                for(int y:next){
                    iner[y]--;
                    if(iner[y]==0) temp.add(y);
                }
            }
            System.out.println();
            for(int x:temp) if(!used[x]) que.offer(x);
        }
        if(ans.size()!=n) System.out.println(-1);
        else {
            for(int x:ans) System.out.print(x+" ");
        }
    }

}

Dijkstra

AcWing 849. Dijkstra求最短路 I