日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[转载] 算法竞赛中的JAVA使用笔记

發布時間:2025/3/11 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [转载] 算法竞赛中的JAVA使用笔记 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

參考鏈接: Java中StringTokenizer類的示例| 1(構造函數)

算法競賽中的JAVA使用筆記?

?

?

?算法競賽中的JAVA使用筆記

? ?輸入與輸出

? ? ?基本輸入輸入掛輸出控制臺輸入輸出重定向到文件 大整數與高精度

? ? ?大整數BigInteger高精度BigDecimal高精度開方 字符串與進制轉換

? ? ?字符串基本操作進制轉換 排序

? ? ?默認排序實現Comparator接口自定義比較器對自定義類的排序用lambda自定義比較器僅 JAVA8 以上支持 CSTL中部分數據結構在JAVA中對應的用法

? ? ?setmapvectorlistpriority_queuequeuestackdeque? ?

?

?

本文介紹了Java在程序算法競賽解題時常用的一些知識,包括基本的輸入輸出、Java的優勢大數高精類、字符串與進制轉換、排序以及C++ STL中部分數據結構在JAVA中對應的用法,旨在作為C/C++選手使用Java解題時的參考,并不會介紹基礎的Java入門語法。?

本文在本人新博客的鏈接:http://www.myblog.link/2016/11/14/Note-of-java/?

?

輸入與輸出?

基本輸入?

Scanner in = new Scanner (System.in);//基本方法

Scanner in = new Scanner (new BufferedInputStream(System.in));//更快

XXX foo = in.nextXXX();//然后這樣給一個XXX類型的變量從標準輸入獲取值

while(in.hasNext()) doSomeThing();//循環到EOF時這么寫,后面也可以加上變量類型?

輸入掛?

class InputReader {

? ? BufferedReader buf;

? ? StringTokenizer tok;

? ? InputReader() {

? ? ? ? buf = new BufferedReader(new InputStreamReader(System.in));

? ? }

? ? boolean hasNext() {

? ? ? ? while (tok == null || !tok.hasMoreElements()) {

? ? ? ? ? ? try {

? ? ? ? ? ? ? ? tok = new StringTokenizer(buf.readLine());

? ? ? ? ? ? } catch (Exception e) {

? ? ? ? ? ? ? ? return false;

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? return true;

? ? }

? ? String next() {

? ? ? ? if (hasNext())

? ? ? ? ? ? return tok.nextToken();

? ? ? ? return null;

? ? }

? ? int nextInt() {

? ? ? ? return Integer.parseInt(next());

? ? }

? ? long nextLong() {

? ? ? ? return Long.parseLong(next());

? ? }

? ? double nextDouble() {

? ? ? ? return Double.parseDouble(next());

? ? }

? ? BigInteger nextBigInteger() {

? ? ? ? return new BigInteger(next());

? ? }

? ? BigDecimal nextBigDecimal() {

? ? ? ? return new BigDecimal(next());

? ? }

}?

輸出?

PrintWriter out = new PrintWriter(new BufferedOutputStream(System.out));//使用緩存加速,比直接使用System.out快

out.println(n);?

out.printf("%.2f\n", ans); // 與c語言中printf用法相同?

控制臺輸入輸出重定向到文件?

FileInputStream fis = new FileInputStream("b.in");??

System.setIn(fis);??

PrintStream ps = new PrintStream(new FileOutputStream("b.out"));??

System.setOut(ps);?

大整數與高精度?

大整數BigInteger?

import java.math.BigInteger;?

//主要有以下方法可以使用:?

BigInteger add(BigInteger other)?

BigInteger subtract(BigInteger other)?

BigInteger multiply(BigInteger other)?

BigInteger divide(BigInteger other)

BigInteger [] dividedandRemainder(BigInteger other) //數組第一位是商,第二位是余數

BigInteger pow(int other)// other次方

BigInteger mod(BigInteger other)?

BigInteger gcd(BigInteger other)?

int compareTo(BigInteger other) //負數則小于,0則等于,正數則大于

static BigInteger valueOf(long x)

//輸出數字時直接使用 System.out.println(a) 即可?

高精度BigDecimal?

BigDecimal add(BigDecimal other)

BigDecimal subtract(BigDecimal other)

BigDecimal multiply(BigDecimal other)

BigDecimal divide(BigDecimal other)

BigDecimal divide(BigDecimal divisor, int scale, BigDecimal.ROUND_HALF_UP)//除數,保留小數位數,保留方法四舍五入

BigDecimal.setScale()方法用于格式化小數點 //setScale(1)表示保留一位小數,默認用四舍五入方式?

高精度開方?

//求sqrt(x),保留前n位數字(不是小數點后n位),n位后直接舍棄(非四舍五入)

private static BigDecimal sqrt(BigDecimal x, int n) {

? ? ? ? BigDecimal ans = BigDecimal.ZERO;

? ? ? ? BigDecimal eps = BigDecimal.ONE;

? ? ? ? for (int i = 0; i < n; ++i) {

? ? ? ? ? ? while (ans.pow(2).compareTo(x) < 0) {

? ? ? ? ? ? ? ? ans = ans.add(eps);

? ? ? ? ? ? }

? ? ? ? ? ? ans = ans.subtract(eps);

? ? ? ? ? ? eps = eps.divide(BigDecimal.TEN);

? ? ? ? }

? ? ? ? return ans;

? ? }?

字符串與進制轉換?

字符串基本操作?

String st = "abcdefg";

char [] ch;

ch = st.toCharArray(); // 字符串轉換為字符數組.

for (int i = 0; i < ch.length; i++){

? ? ch[i] += 1; //字符數組可以像C++ 一樣操作

}

System.out.println(ch); // 輸入為“bcdefgh”.?

進制轉換?

String s = Integer.toString(a, x); //把int型數據轉換乘X進制數并轉換成string型

// 0123456789abcdefghijklmnopqrstuvwxyz, 2<=x<=36

int b = Integer.parseInt(s, x);//把字符串當作X進制數轉換成int型?

排序?

默認排序?

原型:?

Arrays.sort(int[] a, int fromIndex, int toIndex)?

這種形式是對數組部分排序,也就是對數組a的下標從fromIndex到toIndex-1的元素排序,? 注意:下標為toIndex的元素不參與排序哦!?

實現Comparator接口自定義比較器?

原型:?

public static <T> void sort(T[] a,int fromIndex, int toIndex,? Comparator<? super T> c)?

將整形數組從大到小排序:?

public class Main {

? ? public static void main(String[] args) {

? ? ? ? //注意,要想改變默認的排列順序,不能使用基本類型(int,double, char)

? ? ? ? //而要使用它們對應的類

? ? ? ? Integer[] a = {9, 8, 7, 2, 3, 4, 1, 0, 6, 5};

? ? ? ? //定義一個自定義類MyComparator的對象

? ? ? ? Comparator cmp = new MyComparator();

? ? ? ? Arrays.sort(a, cmp);

? ? ? ? for(int i = 0; i < a.length; i ++) {

? ? ? ? ? ? System.out.print(a[i] + " ");

? ? ? ? }

? ? }

}

//Comparator是一個接口,所以這里我們自己定義的類MyComparator要implents該接口

//而不是extends Comparator

class MyComparator implements Comparator<Integer>{

? ? //返回值為負則o1排在o2前面,反正在后面,為0則表示相等

? ? @Override

? ? public int compare(Integer o1, Integer o2) {

? ? ? ? //如果n1小于n2,我們就返回正值,如果n1大于n2我們就返回負值,

? ? ? ? //這樣顛倒一下,就可以實現反向排序了

? ? ? ? if(o1 < o2) {?

? ? ? ? ? ? return 1;

? ? ? ? }else if(o1 > o2) {

? ? ? ? ? ? return -1;

? ? ? ? }else {

? ? ? ? ? ? return 0;

? ? ? ? }

? ? }

}?

對自定義類的排序?

對自己定義的類,除了上述在sort時制定比較器,還可以類似C++重載<,在定義類的時候實現Comparable接口,然后用方法1的語法進行排序,這樣比較簡潔,推薦!? 以下是一個完整例子:?

import java.util.Arrays;

?

class Point implements Comparable<Point>{

? ? ?int x,y;

? ? //自定義的比較函數,跟2的語法類似,此例中先x后y從小到大排序

? ? @Override

? ? public int compareTo(Point o) {

? ? ? ? return x!=o.x? x-o.x: y-o.y;

? ? }

}

?

public class Main {

?

? ? public static void main(String[] args) {

? ? ? ? //Java里的數組要先new數組,再new每個元素,不是數組有了每個元素也就有了

? ? ? ? Point[] p = new Point[3];

? ? ? ? for(int i = 0;i < p.length;++i){

? ? ? ? ? ? p[i] = new Point();

? ? ? ? }

? ? ? ? //不用上面的for把每個元素new出來直接進行下面的賦值會空指針的

? ? ? ? //其實應該在Point里重載有參的構造函數,直接在new的時候初始化,這樣代碼簡潔些

? ? ? ? p[0].x = 3;

? ? ? ? p[0].y = 3;

? ? ? ? p[1].x = 1;

? ? ? ? p[1].y = 4;

? ? ? ? p[2].x = 3;

? ? ? ? p[2].y = 1;

? ? ? ? //sort還可以在第2、3個參數上指定排序起止

? ? ? ? Arrays.sort(p);//先x后y從小到大排序

? ? ? ? for(Point t:p){

? ? ? ? ? ? System.out.println(t.x + " " + t.y);

? ? ? ? }

? ? }

}

?

用lambda自定義比較器(僅 JAVA8 以上支持)?

方法2中對整形數組從大到小排序使用lambda可以直接寫成:?

Arrays.sort(a, (x,y)->(y-x));?

方法3中排序自定義的Point類,不需要實現Comparable接口,可以直接這樣:?

Arrays.sort(p, (a,b)->(a.x!=b.x?a.x-b.x:a.y-b.y));?

C++STL中部分數據結構在JAVA中對應的用法?

set?

如果要像C++中使用set進行去重,或者查詢是否存在這方面的應用,在Java中主要使用HashSet類。? HashSet定義、插入、查詢是否存在、刪除元素的例子如下:?

Set<Integer> s = new HashSet<Integer>();//無序,對應標準C++的unordered_set

s.add(1);

System.out.println(s.contains(1) ?? "1 is in set s" : "1 isn't in set s");

//根據key刪除元素

m.remove(1);?

Set遍歷放在下文的Map中演示,因為Java中Map是轉化為Set遍歷的。?

HashSet中元素是無序的(可以理解為順序不確定),LinkedHashSet是遍歷時是按照插入順序排序的,TreeSet是升序排列的,最接近C++中的set,但是在沒有要求元素有序的情況下,Java中一般是使用HashSet的(因為復雜度的優勢?我感覺是這樣的),這也是我在例子中使用HashSet來對應set的原因(其實我感覺C++中這種情況使用unordered_set會更好啊,可能是因為C++11才出現,比較晚,所有不普及)。下節的map的情況與之類似。如果使用有序的TreeSet,還可以進行如下的查找操作:?

TreeSet<Integer> s = new TreeSet<Integer>();

//使用s.add(1);等把1-5都加進去,代碼省略

System.out.println(s.ceiling(3));? ?//>=3的最小的數,輸出3

System.out.println(s.floor(3));? ? ?//<=3的最大的數,輸出3

System.out.println(s.higher(3));? ? //>3的最小的數,輸出4

System.out.println(s.lower(3));? ? ?//<3的最大的數,輸出2

System.out.println(s.headSet(3));? ?//<3的數組成的TreeSet,輸出[1, 2]

System.out.println(s.tailSet(3));? ?//>=3的數組成的TreeSet,輸出[3, 4, 5]

System.out.println(s.subSet(2,4));? //>=2且<4的數組成的TreeSet,輸出[2, 3]

System.out.println(s.subSet(2,false,4,true));? ?//>2且<=4的數組成的TreeSet,輸出[3, 4]?

map?

如果只需要C++中map的key對value的映射功能,而不關心順序,Java中一般使用HashMap類,例子如下:?

//這里使用的是HashMap,是無序的,對于標準C++的unordered_map

//定義與存取

Map<Integer, Integer> m = new HashMap<Integer, Integer>();

m.put(1, 111);

System.out.println(m.get(1));//如果get一個不存在的key,則返回null,否則返回對應value

//用迭代器遍歷

Iterator<Entry<Integer, Integer>> it = m.entrySet().iterator();

while(it.hasNext()){

? ?Entry<Integer, Integer> e = it.next();

? ?System.out.println(e.getKey() + " " + e.getValue());

}

//根據key刪除元素

m.remove(1);

//用for-each循環遍歷

for(Map.Entry<Integer, Integer> e:m.entrySet()){

? ?System.out.println(e.getKey() + " " + e.getValue());

}?

如需有序,與Set類似,有LinkedHashMap、TreeMap等類可以使用。?

vector?

在Java中,C++的vector對應的是ArrayList類。雖然Java中也有Vector這個類,但它是歷史遺留下來的,不建議使用。?

ArrayList<Integer> a = new ArrayList<Integer>();//創建一個儲存整形的ArrayList

a.add(1);? ?//向其最后添加“1”這個元素

a.add(2);? ?//向其最后添加“2”這個元素

a.add(1, 3);? ? //向其index為1的位置添加“3”這個元素,原來index為1及后續元素向后順延一位;index以0起始

System.out.println(a);? //輸出a,結果為[1, 3, 2]

a.remove(1);? ? //刪除index為1的元素,注意不是刪除值為1的元素

System.out.println(a);? //輸出a,結果為[1, 2]

a.remove(Integer.valueOf(1));? ?//刪除值為1的元素

System.out.println(a);? //輸出a,結果為[2]

a.set(0, 1);? ? //將index為0的元素的值改成1

System.out.println(a.get(0));? ?//取出index為0的元素并輸出,結果為1?

list?

在Java 中,C++的list對于LinkedList類,其基本用法跟ArrayList類似,只是實現上使用鏈表而不是數組,從而在一些操作的復雜度上有變化,將上文代碼的ArrayList改為LinkedList可直接使用,故在此省略。(其實它還實現了C++中queue、deque、stack等的功能,有使用鏈表實現的這些數據結構的需求的話可以用它。)?

priority_queue?

在Java中,C++的priority_queue對應的是PriorityQueue類(終于碰到名字像的了?用起來都是坑啊)。示例如下:?

PriorityQueue<Integer> pq = new PriorityQueue<Integer>();//定義一個儲存整形的優先隊列,值【小】的在前

pq.offer(1);//將1添加進去,不能用add(),雖然能過編譯!!!

pq.offer(3);

pq.offer(2);

//跟C++的不同,你可以遍歷它,但是你會發現遍歷的結果并不是排序了的……我這里輸出1 3 2?

for(int t :pq){

? ? System.out.print(t + " ");

}

System.out.println();

System.out.println(pq.peek());//取出第一個值(默認是最【小】的那個),并不刪除它,這句代碼輸出1!!!

System.out.println(pq.poll());//取出第一個值(默認是最【小】的那個),并且刪除它,這句代碼輸出1!!!

System.out.println(pq);//輸出剩下的元素,結果是[2, 3],但是并不是排序之后的!!!這只是巧合,不信試試其他值?

用起來發現方法名都變得不認識了,可以遍歷但是又無序,取數據的時候默認還是取最小的,跟C++相反。當然,可以自定義比較器:?

class MyComp implements Comparator<Integer> {

? ? @Override

? ? public int compare(Integer o1, Integer o2) {

? ? ? ? return o2 - o1;

? ? }

}

?

public class Main {

? ? public static void main(String[] args) {

? ? ? ? PriorityQueue<Integer> pq = new PriorityQueue<Integer>(new MyComp());

? ? ? ? // ……

? ? }

}?

覺得麻煩?那就直接lambda搞起?

PriorityQueue<Integer> pq2 = new PriorityQueue<Integer>((a, b) -> (b - a));?

queue?

C++中的queue在Java中可以使用ArrayDeque類,實例如下:?

ArrayDeque<Integer> queue = new ArrayDeque<Integer>();

queue.offer(1);//成功返回true,失敗返回false,別寫成push了,否則……看看下個例子就知道了

queue.offer(2);

queue.offer(3);

System.out.println(queue.peek());//類似于C++中queue的front(),返回第一個元素

while (!queue.isEmpty()) {

? ? System.out.println(queue.pop());//跟C++中的queue()一樣可以刪除第一個元素,但是會返回它,不像C++中是void的

}?

上述代碼的輸出為1、1、2、3(我就不換行了)。?

stack?

C++中的stack在Java中使用ArrayDeque類(你沒看錯,還是它,我知道Java也有Stack類,那也是歷史遺留問題),語法基本相同,下面是例子:?

ArrayDeque<Integer> stack = new ArrayDeque<Integer>();

stack.push(1);//跟上面那個代碼的不同之處就在這了

stack.push(2);

stack.push(3);

System.out.println(stack.peek());//類似于C++中stack的top(),返回棧頂元素

while(!stack.isEmpty()){

? ? System.out.println(stack.pop());//跟C++中的pop()一樣可以彈出棧頂元素,但是會返回它,不像C++中是void的

}?

上述代碼的輸出為3、3、2、1(我就不換行了)。?

deque?

deque對應的……不用說了,就是ArrayDeque了。如果你已經被上面的方法名搞暈了的話,試試用下面幾個:?

ArrayDeque<Integer> deque = new ArrayDeque<Integer>();

deque.addFirst(2);

deque.addFirst(1);//往頭加

deque.addLast(3);//往尾加

System.out.println(deque.getFirst());//從頭取

System.out.println(deque.getLast());//從尾取

System.out.println(deque.removeFirst());//從頭刪

System.out.println(deque.removeLast());//從尾刪?

以上代碼輸出1、3、1、3。這些方法加入的時候已經滿了則拋出IllegalStateException異常,讀取或刪除的時候為空則拋出NoSuchElementException異常。?

不要忘了ArrayDeque是可以遍歷的喲,包括把它當stack或者queue用的時候……

總結

以上是生活随笔為你收集整理的[转载] 算法竞赛中的JAVA使用笔记的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。