title: acwing基礎算法
date: 2021-01-23 09:22:59
tags:
-算法
-acwing
categories: 算法
從今天開始acwing的學習,預計基礎班一周看完和寫完,懷挺!!!
acwing基礎班一
快速排序
步驟
注意快排的核心思想是分治法:
分解:兩個片段,一個大於x,一個小於x,並且遞歸的調用,partition
解決:和分治合在一起即partition
合並:無特別步驟,自動合並(在左右端點到達最小以后)
關鍵步驟在於2
解決方法
1、暴力開空間
開辟兩個空間,分別放置大於小於x的數,再合並
時間O(n),空間O(n)
2、partition法
Scanner類的用法參考https://www.runoob.com/java/java-scanner-class.html
package acwing基礎算法;
import java.io.BufferedInputStream;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Scanner;
public class quicksort {
public static void quick_sort(int []arr,int l,int r){
if(l>=r) return;
int i=l-1,j=r+1,x=arr[l];
while(i<j){
do i++;while(arr[i]<x);
do j--;while (arr[j]>x);
if(i<j){
int t=arr[i];
arr[i]=arr[j];
arr[j]=t;
}
}
quick_sort(arr,l,j);
quick_sort(arr,j+1,r);
}
public static void main(String[] args) {
Scanner scannerIn = new Scanner(new BufferedInputStream(System.in));
//獲取數組長度,並分配數組空間
int n = scannerIn.nextInt();
int q[]=new int[n];
//為數組賦值
for(int i=0;i<n;i++){
q[i]=scannerIn.nextInt();
}
quick_sort(q ,0,n-1);
//打印數組
System.out.println(Arrays.toString(q));
}
}
3、快速選擇算法
import java.io.BufferedInputStream;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Scanner;
//改寫快速排序算法
public class Main {
public static int quick_sort(int []arr,int l,int r,int k){
if(l==r) return arr[l];
int i=l-1,j=r+1,x=arr[l];
while(i<j){
do i++;while(arr[i]<x);
do j--;while(arr[j]>x);
if(i<j){
int t=arr[i];
arr[i]=arr[j];
arr[j]=t;
}
}
if(k<=j-l+1)
return quick_sort(arr,l,j,k);
else
return quick_sort(arr,j+1,r,k-(j-l+1));
}
public static void main(String[] args) {
Scanner scannerIn = new Scanner(new BufferedInputStream(System.in));
//獲取數組長度,並分配數組空間
int n = scannerIn.nextInt();
int k = scannerIn.nextInt();
int q[]=new int[n];
//為數組賦值
for(int i=0;i<n;i++){
q[i]=scannerIn.nextInt();
}
//打印結果
System.out.print(quick_sort(q ,0,n-1,k-1));
}
}
注意事項
1、邊界問題:理論上可以選取樞紐元素問題時可以選擇l,r和(l+r)/2,隨機選擇
但是注意邊界條件,當選擇i和i-1作為遞歸界時,不能使用l作為樞紐元素;
同理不能使用j,j+1作為遞歸界,當使用r作為樞紐元素時
用r+l>>1時如果是用i做邊界要變成r+l+1>>1
2、停止一次partition的可能情況i=j或者i+1=j
3、快速排序的partition有多種寫法,常見的還有算法導論上的寫法,同向移動雙指針(了解即可)
4、快排是不穩定排序,可以把快排的數變成二維(有下標)這樣每個數都不相同了,變成穩定的
歸並排序
基本思想
算法
package acwing基礎算法;
import java.io.BufferedInputStream;
import java.util.Arrays;
import java.util.Scanner;
public class MergeSort {
public static void merge_sort(int l,int r,int []arr){
if(l>=r) return;
//防止溢出
int mid=l+((r-l)>>1);
merge_sort(l,mid,arr);
merge_sort(mid+1,r,arr);
//我們不希望arr的引用發生改變,因為arr的引用發生改變,那么需要再次返回一個arr的引用給q,但是這里arr是局部變量
//因此我們希望arr指向的內容發生改變
merge(l,mid,r,arr);
};
private static int[]q;
private static int[]temp;
public static void merge(int l,int mid,int r,int []arr){
temp=new int[r-l+1];
int i=l,j=mid+1,index=0;
while(i<=mid&&j<=r){
if(arr[i]<=arr[j])
temp[index++]=arr[i++];
else
temp[index++]=arr[j++];
}
while(i<=mid) temp[index++]=arr[i++];
while(j<=r) temp[index++]=arr[j++];
for(i=l,j=0;i<=r;i++,j++) arr[i]=temp[j];
// return temp;
};
public static void main(String[] args) {
Scanner scannerIn = new Scanner(new BufferedInputStream(System.in));
int n = scannerIn.nextInt();
q = new int[n];
for(int i=0;i<n;i++){
q[i] = scannerIn.nextInt();
}
merge_sort(0,n-1,q);
System.out.println(Arrays.toString(q));
scannerIn.close();
}
}
注意事項
1、出錯點1是因為我在合並時的條件寫的是<實際應該是<=,即等於也需要被算進輔助數組
2、一定要注意數組傳遞是引用傳遞,即變量名指向的地址發生變化。因此形參傳遞數組,就是局部變量指向了被傳遞的數組,同理局部返回數組名,就是返回了局部的數組地址。(局部數組后被釋放,需要改成全局數組)
3、最簡單的做法就是在merge函數中直接改變arr數組的值,因為arr數組指向的就是q數組
4、 int mid=l+((r-l)>>1);是為了防止溢出
5、 temp=new int[r-l+1];不要錯寫成分配成new int[arr.length];
二分
整數二分
有單調性的一定可以二分,但能二分的不一定有單調性
深刻認識,就是滿足某一條件的最大值或者滿足某一條件的最小值,縮小區間來尋找這個介於滿足與不滿足之間的臨界值
l=mid時,我們選擇mid=(l+r+1)/2,為了避免死循環
如果無解一定與題目有關
模板
import java.io.BufferedInputStream;
import java.util.Scanner;
public class Main {
public static void twoDivide(int[]arr,int target){
int l=0,r=arr.length-1;
while (l<r){
int mid=l+r>>1;
if(arr[mid]>=target) r=mid;
else l=mid+1;
}
if(arr[l]!=target)
System.out.println("-1 -1");
else {
System.out.print(l+" ");
l=0;r=arr.length-1;
while (l < r) {
int mid = l + r + 1 >> 1;
if (arr[mid] <= target) l = mid;
else r = mid - 1;
}
System.out.println(l);
}
}
public static void main(String[] args) {
Scanner in = new Scanner(new BufferedInputStream(System.in));
int n = in.nextInt();
int []q=new int[n];
int k=in.nextInt();
for(int i=0;i<n;i++){
q[i]=in.nextInt();
}
while(k--!=0){
twoDivide(q,in.nextInt());
}
}
}
浮點數二分
寫法一
和整數二分模板一樣,但是mid不再加1減1,且判斷條件有個臨界值,一般比精度大10的-2次方
package acwing基礎算法;
import java.io.BufferedInputStream;
import java.util.Scanner;
public class DoubleTwoDivide {
public static void main(String[] args) {
Scanner in = new Scanner(new BufferedInputStream(System.in));
double x = in.nextDouble(),l=0,r=Math.abs(x);
while(r-l>1e-8){
double mid=(l+r)/2;
if(mid*mid*mid>=Math.abs(x))r=mid;
else l=mid;
}
boolean flag;
if (x>=0)
flag=true;
else
flag=false;
System.out.println(String.format("%.6f",flag?l:-l));
}
}
寫法二
直接for循環一百次或者縮小范圍,那精度絕對是夠的
public class Main{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
double num = sc.nextDouble();
boolean flag = false;
if(num < 0) {
flag = true;
num = -num;
}
double l = 0d, r = 100d;
while (r - l > 1e-8) {
double mid = (l + r) / 2;
if(mid * mid * mid < num) {
l = mid;
} else {
r = mid;
}
}
System.out.println(String.format("%.6f", flag? -l:l));
}
}
高精度加法
BufferedReader類的用法
以下內容參考至https://blog.csdn.net/StrongHelper/article/details/84697087
System.in的類型可以歸結為節點流、字節流、輸入流;
InputStreamReader這個對象是處理流,字符流,輸入流;
BufferedReader的類型是緩沖處理流、字符流、輸入流。
類 InputStreamReader是字節流通向字符流的橋梁:它使用指定的 charset 讀取字節並將其解碼為字符。它使用的字符集可以由名稱指定或顯式給定,或者可以接受平台默認的字符集。如:GBK
每次調用 InputStreamReader 中的一個 read() 方法都會導致從底層輸入流讀取一個或多個字節。要啟用從字節到字符的有效轉換,可以提前從底層流讀取更多的字節,使其超過滿足當前讀取操作所需的字節。 為了達到最高效率,可要考慮在 BufferedReader 內包裝 InputStreamReader。例如: BufferedReader in= new BufferedReader(new InputStreamReader(System.in));
System.in是個字節流
InputStreamReader是個字符流和字節流之間的轉換中介
BufferedReader是個字符流
整體意思就是用InputStreamReader這個中介把System.in這個字節流轉換成字符流BufferedReader
這樣輸入的時候就可以不是一個一個字節讀,而是一個一個字符讀,再加上是個Buffer,效率會高很多。
InputStream is = System.in;//鍵盤輸入流
InputStreamReader isr = new InputStreamReader(is);//字節流轉換為字符流
BufferedReader bufr = new BufferedReader(isr);//把字符流添加到緩沖流
BigInteger用法
以下內容參考自https://blog.csdn.net/qq_41668547/article/details/87628618
java中可以使用BigInteger操作大整數,也可以轉換進制。如果在操作的時候一個整型數據已經超過了整數的最大類型長度long的話,則此數據就無法裝入,所以,此時要使用BigInteger類進行操作。這些大數都會以字符串的形式傳入
split的用法
參考自https://www.cnblogs.com/xiaoxiaohui2015/p/5838674.html
算法模板
package acwing基礎算法;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigInteger;
public class HighPrecision {
public static void main(String[] args) throws IOException {
// highAdd();
// highSub();
// highMultiply();
highDivide();
}
public static void highAdd() throws IOException {
BufferedReader cin = new BufferedReader(new InputStreamReader(System.in));
String[] s = cin.readLine().split(" ");
BigInteger n = new BigInteger(s[0]);
// System.out.println(1);
s = cin.readLine().split(" ");
BigInteger m = new BigInteger(s[0]);
System.out.println(m.add(n));
}
public static void highSub() throws IOException {
BufferedReader cin = new BufferedReader(new InputStreamReader(System.in));
String[] s = cin.readLine().split(" ");
BigInteger n = new BigInteger(s[0]);
// System.out.println(1);
s = cin.readLine().split(" ");
BigInteger m = new BigInteger(s[0]);
System.out.println(n.subtract(m));
}
public static void highMultiply() throws IOException {
BufferedReader cin = new BufferedReader(new InputStreamReader(System.in));
String[] s = cin.readLine().split(" ");
BigInteger n = new BigInteger(s[0]);
// System.out.println(1);
s = cin.readLine().split(" ");
BigInteger m = new BigInteger(s[0]);
System.out.println(n.multiply(m));
}
public static void highDivide() throws IOException {
BufferedReader cin = new BufferedReader(new InputStreamReader(System.in));
String[] s = cin.readLine().split(" ");
BigInteger n = new BigInteger(s[0]);
// System.out.println(1);
s = cin.readLine().split(" ");
BigInteger m = new BigInteger(s[0]);
System.out.println(n.divide(m));
// System.out.println(n.divide(m).multiply(m));
// System.out.println(n.subtract(n.divide(m).multiply(m)));
System.out.println(n.remainder(m));
}
}
前綴和
算法思想
我們把S0定義成0
算法模板
package acwing基礎算法;
import com.sun.org.apache.bcel.internal.Const;
import java.io.BufferedInputStream;
import java.util.Scanner;
public class PreSum {
private static final int N=100010;
public static void main(String[] args) {
Scanner in = new Scanner(new BufferedInputStream(System.in));
int n = in.nextInt();
//m次輸入
int m = in.nextInt();
int[] q = new int[N];
int[] s = new int[N];
//輸入數組
for (int i = 1; i <= n; i++) {
q[i]=in.nextInt();
}
for(int i=1;i<=n;i++){
s[i]=s[i-1]+q[i];
}
//m次結果輸出
while(m--!=0){
//輸入數的范圍l,r
int l=in.nextInt(),r=in.nextInt();
System.out.println(s[r]-s[l-1]);
}
}
}
多維
上面修正為加最后一個式子修正為加Sx1-1,y-1
package acwing基礎算法;
import java.io.BufferedInputStream;
import java.util.Scanner;
public class PreMultiSum {
private static final int N = 1010;
public static void main(String[] args) {
Scanner in = new Scanner(new BufferedInputStream(System.in));
//n行
int n = in.nextInt();
//m列
int m = in.nextInt();
int q = in.nextInt();
int [][]a = new int[N][N];
int [][]s = new int[N][N];
//二維數組賦值
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
a[i][j] = in.nextInt();
}
//求完整和
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
s[i][j] = s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j];
}
//求部分和
while(q--!=0){
int x1=in.nextInt(),y1=in.nextInt(),x2=in.nextInt(),y2=in.nextInt();
System.out.println(s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1]);
}
}
}
差分
前綴和的逆運算
模板
package acwing基礎算法;
import java.io.BufferedInputStream;
import java.util.Scanner;
public class Difference {
private static final int N=100010;
public static void insert(int l,int r,int x,int []b){
b[l]+=x;
b[r+1]-=x;
}
public static void main(String[] args) {
Scanner in = new Scanner(new BufferedInputStream(System.in));
int n = in.nextInt(),m = in.nextInt();
int[] a = new int[N];
int[] b = new int[N];
//給a數組賦值
for(int i=1;i<=n;i++){
a[i]=in.nextInt();
}
//按a數組構造b數組
for(int i=1;i<=n;i++){
insert(i,i,a[i],b);
}
//多次輸入,給出每次修改的差分數列后的結果
while(m--!=0){
int l=in.nextInt(),r=in.nextInt(),c=in.nextInt();
insert(l,r,c,b);
}
//重新求和數列同時注意b[0]等於0
for(int i=1;i<=n;i++){
b[i]+=b[i-1];
}
for(int i=1;i<=n;i++){
System.out.print(b[i]+" ");
}
}
}
差分矩陣
算法思想
超時
scanner超時
import java.io.BufferedInputStream;
import java.util.Scanner;
public class Main {
private static final int N=1010;
public static void insert(int x1,int y1,int x2,int y2,int c,int [][]b){
b[x1][y1]+=c;
b[x2+1][y1]-=c;
b[x1][y2+1]-=c;
b[x2+1][y2+1]+=c;
}
public static void main(String[] args) {
Scanner in = new Scanner(new BufferedInputStream(System.in));
int n = in.nextInt(),m = in.nextInt();//n行m列
int q = in.nextInt();//q次運算
int [][]a = new int[N][N];
int [][]b = new int[N][N];
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
a[i][j]=in.nextInt();
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
insert(i,j,i,j,a[i][j],b);
while(q--!=0){
int x1 = in.nextInt(),y1 = in.nextInt(),x2 = in.nextInt(),y2 = in.nextInt(),c = in.nextInt();
insert(x1,y1,x2,y2,c,b);
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++) {
b[i][j] += b[i - 1][j] + b[i][j - 1] - b[i - 1][j - 1];
}
for(int i=1;i<=n;i++) {
for (int j = 1; j <= m; j++) {
System.out.print(b[i][j] + " ");
}
System.out.println();
}
}
}
輸入流還是超時
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;
public class Main {
private static final int N=1010;
public static void insert(int x1,int y1,int x2,int y2,int c,int [][]b){
b[x1][y1]+=c;
b[x2+1][y1]-=c;
b[x1][y2+1]-=c;
b[x2+1][y2+1]+=c;
}
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String[] s1 = reader.readLine().split(" ");
int n = Integer.parseInt(s1[0]),m = Integer.parseInt(s1[1]);
int q = Integer.parseInt(s1[2]);
int [][]a = new int[N][N];
int [][]b = new int[N][N];
for(int i=1;i<=n;i++) {
String[] s2 = reader.readLine().split(" ");
for (int j = 1; j <= m; j++) {
a[i][j] = Integer.parseInt(s2[j - 1]);
insert(i, j, i, j, a[i][j], b);
}
}
while(q--!=0){
String[] s3 = reader.readLine().split(" ");
int x1 = Integer.parseInt(s3[0]),
y1 = Integer.parseInt(s3[1]),
x2 = Integer.parseInt(s3[2]),
y2 = Integer.parseInt(s3[3]),
c = Integer.parseInt(s3[4]);
insert(x1,y1,x2,y2,c,b);
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++) {
b[i][j] += b[i - 1][j] + b[i][j - 1] - b[i - 1][j - 1];
}
for(int i=1;i<=n;i++) {
for (int j = 1; j <= m; j++) {
System.out.print(b[i][j] + " ");
}
System.out.println();
}
}
}
BufferedReader BufferedWriter加輸入輸出流
輸入流再加輸出流不超時
package acwing基礎算法;
import java.io.*;
import java.util.Scanner;
public class DifferenceMulti {
private static final int N=1010;
public static void insert(int x1,int y1,int x2,int y2,int c,int [][]b){
b[x1][y1]+=c;
b[x2+1][y1]-=c;
b[x1][y2+1]-=c;
b[x2+1][y2+1]+=c;
}
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
//BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));
String[] s1 = reader.readLine().split(" ");
int n = Integer.parseInt(s1[0]),m = Integer.parseInt(s1[1]);
int q = Integer.parseInt(s1[2]);
int [][]a = new int[N][N];
int [][]b = new int[N][N];
for(int i=1;i<=n;i++) {
String[] s2 = reader.readLine().split(" ");
for (int j = 1; j <= m; j++) {
a[i][j] = Integer.parseInt(s2[j - 1]);
insert(i, j, i, j, a[i][j], b);
}
}
while(q--!=0){
String[] s3 = reader.readLine().split(" ");
int x1 = Integer.parseInt(s3[0]),
y1 = Integer.parseInt(s3[1]),
x2 = Integer.parseInt(s3[2]),
y2 = Integer.parseInt(s3[3]),
c = Integer.parseInt(s3[4]);
insert(x1,y1,x2,y2,c,b);
}
for(int i=1;i<=n;i++) {
for (int j = 1; j <= m; j++) {
b[i][j] += b[i - 1][j] + b[i][j - 1] - b[i - 1][j - 1];
//輸出
writer.write(b[i][j] + " ");
}
writer.write("\n");
}
writer.flush();
reader.close();
writer.close();
}
}
雙指針算法
算法思想
最大不連續子數組
模板
import java.io.*;
public class Main {
private static final int N = 100010;
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
String[] s = in.readLine().split(" ");
int n = Integer.parseInt(s[0]);
int[] a = new int[N];
//q是hash數組
int[] q = new int[N];
String[] s1 = in.readLine().split(" ");
for(int i=1;i<=n;i++){
a[i]=Integer.parseInt(s1[i-1]);
}
//雙指針算法
//定義雙指針
//res表示最大的長度
int res=0;
for(int i=1,j=1;i<=n;i++){
q[a[i]]++;
while(j<=i&&q[a[i]]>1)q[a[j++]]--;
res=Math.max(res,i-j+1);
}
out.write(res+" ");
out.flush();
in.close();
out.close();
}
位運算
右移
lowbit
應用
求解x的補碼中1的個數
模板
import java.io.*;
public class Main{
private static final int N = 100010;
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
String[] s = in.readLine().split(" ");
int n = Integer.parseInt(s[0]);
int[] a = new int[N];
String[] s1 = in.readLine().split(" ");
for(int i=1;i<=n;i++){
a[i]=Integer.parseInt(s1[i-1]);
}
int i = 1;
while(n--!=0){
int k = 0;
while(a[i]!=0){
a[i]-=a[i]&(-a[i]);
k++;
}
i++;
out.write(k+" ");
}
out.flush();
in.close();
out.close();
}
}
補充
1、原碼、反碼、補碼
2、解題思路
離散化
算法思想
模板
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Main {
private static final int N = 300010;
public static void main(String[] args) throws IOException {
//輸入m,n
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String[] str = in.readLine().split(" ");
//m行每行查詢,n行每行指定下標加
int n = Integer.parseInt(str[0]),m = Integer.parseInt(str[1]);
//a數組用來裝所有x和c和計算結果,sum數組用來裝前綴和
int[] a = new int[N],sum = new int[N];
//all數組用來裝所有的下標,收集所有下標,進行離散化
List<Integer> all = new ArrayList<>();
List<Pairs> add = new ArrayList<>();
//query用來裝輸入的所有的查詢下標
List<Pairs> query = new ArrayList<>();
//輸入並放入add數組和all數組
for(int i=1;i<=n;i++){
String[] s2 = in.readLine().split(" ");
int x = Integer.parseInt(s2[0]),c = Integer.parseInt(s2[1]);
add.add(new Pairs(x,c));
all.add(x);
}
//輸入並放入query數組和all數組
for(int i=1;i<=m;i++){
String[] s3 = in.readLine().split(" ");
int l = Integer.parseInt(s3[0]),r = Integer.parseInt(s3[1]);
query.add(new Pairs(l,r));
all.add(l);all.add(r);
}
//開始離散化
//1.排序
Collections.sort(all);
//2.去重
int j=0;
for(int i=0;i<all.size();i++){
if(i==0||all.get(i)!=all.get(i-1)){
all.set(j,all.get(i));
j++;
}
}
all = all.subList(0, j); //將去重后的List保存下來,或者此處也可以將unique作為最后一個數,用r作為二分
//指定位置加
for(Pairs items:add){
int index=find(items.first,all);
a[index]+=items.second;
}
//求前綴和
for(int i=1;i<=all.size();i++) sum[i] = sum[i-1] + a[i];
//查詢
for(Pairs items:query) {
int l = find(items.first, all);
int r = find(items.second, all);
System.out.println(sum[r] - sum[l - 1]);
}
}
//查找函數(離散化映射函數,在離散化數組中找到映射的下標)
public static int find(int x,List<Integer> list){
int l=0,r=list.size()-1;
while(l<r) {
int mid = l+r>>1;
if (list.get(mid) >= x) r = mid;
else l = mid + 1;
}
return l+1;
}
};
class Pairs{
public int first;
public int second;
public Pairs(int first,int second){
this.first = first;
this.second = second;
}
}
注意
1、all數組由list裝載,因此下標從0開始,去重和進行查找函數時都從0開始。映射到1,n,所以查找離散函數時返回l+1
2、去重后改變all數組的長度all = all.subList(0, j);可以縮小定點相加和求前綴和的時間復雜度
補充
1、返回數組中所有不同的數
雙指針
2、java去重
區間合並
區間有交集或者端點重合的區間可以合並為同一個區間
package acwing基礎算法;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class SectionMerge {
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String[] s1 = in.readLine().split(" ");
//n行輸入
int n = Integer.parseInt(s1[0]);
//輸入數組
// int[] a = new int[N];
List<Pairs> list = new ArrayList<>();
List<Pairs> res = new ArrayList<>();
for(int i=0;i<n;i++){
String[] s2 = in.readLine().split(" ");
int l = Integer.parseInt(s2[0]),r = Integer.parseInt(s2[1]);
list.add(new Pairs(l,r));
}
//排序
list.sort(new Comparator<Pairs>() {
@Override
public int compare(Pairs o1, Pairs o2) {
return o1.first-o2.first;
}
});
//現在維護的線段
int st = Integer.MIN_VALUE,ed=Integer.MIN_VALUE;
for(Pairs items:list){
// System.out.println(ed);
if(ed<items.first){
if(st!=Integer.MIN_VALUE) res.add(new Pairs(st,ed));
st = items.first; ed = items.second;
}
else{
ed = Math.max(ed,items.second);
}
}
if(st != Integer.MIN_VALUE) res.add(new Pairs(st,ed));
System.out.println(res.size());
}
}
class Pairs{
int first;
int second;
public Pairs(int first, int second) {
this.first = first;
this.second = second;
}
}
注意
最后還要再進行一次res.add,並且去除輸入數組為空的情況
習題:格子染色