算法练习day8——190326(猫狗队列、转圈打印矩阵、旋转正方形矩阵、反转单向双向链表、数N的加法组合)
1.貓狗隊列
【題目】 寵物、 狗和貓的類如下:
public class Pet {private String type;public Pet(String type) {this.type = type;}public String getPetType() {return this.type;} }public class Dog extends Pet {public Dog() {super("dog");} }public class Cat extends Pet {public Cat() {super("cat");} }實現(xiàn)一種狗貓隊列的結(jié)構(gòu), 要求如下:
- 用戶可以調(diào)用add方法,將cat類或dog類的實例放入隊列中;
- 用戶可以調(diào)用pollAll方法, 將隊列中所有的實例按照進隊列的先后順序依次彈出;
- 用戶可以調(diào)用pollDog方法, 將隊列中dog類的實例按照進隊列的先后順序依次彈出;
- 用戶可以調(diào)用pollCat方法, 將隊列中cat類的實例按照進隊列的先后順序依次彈出;
- 用戶可以調(diào)用isEmpty方法, 檢查隊列中是否還有dog或cat的實例;
- 用戶可以調(diào)用isDogEmpty方法, 檢查隊列中是否有dog類的實例;
- 用戶可以調(diào)用isCatEmpty方法, 檢查隊列中是否有cat類的實例。
1.1 分析
使用兩個隊列實現(xiàn):
add():當(dāng)寵物進入結(jié)構(gòu)時:
- 若寵物為狗,則進入Dog隊列;
- 若為貓,則進入Cat隊列。
pollDog():從Dog隊列取頭一個狗;
pollCat():從Cat隊列取頭一個貓;
pollAll():得設(shè)置一個計數(shù)器count,作為時間戳,進來一個寵物,無論貓狗,count++,賦給這個寵物的count,取出時,由Dog隊列和Cat隊列的頭一個的count來判斷哪個寵物進的早點。
isEmpty():Dog隊列和Cat隊列都為空時返回true;
isDogEmpty():Dog隊列為空時返回true;
isDogEmpty():Cat隊列為空時返回true;
1.2 代碼實現(xiàn)
注:不能更改給定的Pet、Cat、Dog類,需自己寫其他的類實現(xiàn)以上功能。
package Solution;import java.util.LinkedList; import java.util.Queue;class Pet {private String type;public Pet(String type) {this.type = type;}public String getPetType() {return this.type;} }class Dog extends Pet {public Dog() {super("dog");} } class Cat extends Pet {public Cat() {super("cat");} }class PetQueue{private Pet pet;private long count;public PetQueue(Pet pet, long count) {this.pet=pet;this.count=count;}public Pet getPet() {return this.pet;}public long getCount() {return this.count;}public String getPetType() {return this.pet.getPetType();} } public class CatDogQueue {private Queue<PetQueue> DogQ;private Queue<PetQueue> CatQ;long count;//計數(shù)器public CatDogQueue() {this.DogQ=new LinkedList<PetQueue>();this.CatQ=new LinkedList<PetQueue>();this.count=0;}public void add(Pet pet) {//根據(jù)類型入相應(yīng)的隊列if(pet.getPetType().equals("cat"))CatQ.add(new PetQueue(pet,count++));else if(pet.getPetType().equals("dog"))DogQ.add(new PetQueue(pet,count++));elsethrow new RuntimeException("err, not dog or cat");}public Pet pollAll() {if(!DogQ.isEmpty()&&!CatQ.isEmpty())if(DogQ.peek().getCount()<CatQ.peek().getCount())//越小越早return this.DogQ.poll().getPet();elsereturn this.CatQ.poll().getPet();else if(!DogQ.isEmpty())return this.DogQ.poll().getPet();else if(!CatQ.isEmpty())return this.CatQ.poll().getPet();elsethrow new RuntimeException("err, queue is empty!");}public Dog pollDog() {if(!DogQ.isEmpty())return (Dog)this.DogQ.poll().getPet();elsethrow new RuntimeException("err, Dog queue is empty!");}public Cat pollCat() {if(!CatQ.isEmpty())return (Cat)this.CatQ.poll().getPet();elsethrow new RuntimeException("err, Cat queue is empty!");}public boolean isEmpty() {return this.DogQ.isEmpty()&&this.CatQ.isEmpty();}public boolean isDogQueueEmpty() {return this.DogQ.isEmpty();}public boolean isCatQueueEmpty() {return this.CatQ.isEmpty();}public static void main(String[] args) {CatDogQueue test = new CatDogQueue();Pet dog1 = new Dog();Pet cat1 = new Cat();Pet dog2 = new Dog();Pet cat2 = new Cat();Pet dog3 = new Dog();Pet cat3 = new Cat();test.add(dog1);test.add(cat1);test.add(dog2);test.add(cat2);test.add(dog3);test.add(cat3);System.out.println(test.pollAll().getPetType());System.out.println(test.pollDog().getPetType());System.out.println(test.pollCat().getPetType());while (!test.isDogQueueEmpty()) {System.out.println(test.pollDog().getPetType());}while (!test.isEmpty()) {System.out.println(test.pollAll().getPetType());}} }運行結(jié)果:
2.轉(zhuǎn)圈打印矩陣
【題目】 給定一個整型矩陣matrix, 請按照轉(zhuǎn)圈的方式打印它。例如: 1 2 3 4 5 6 7 8 9 10 11 12 13 14? 15 16 打印結(jié)果為: 1, 2, 3, 4, 8, 12, 16, 15, 14, 13, 9,5, 6, 7, 11, 10
【要求】 額外空間復(fù)雜度為O(1)
另一篇已寫過
2.1 分析
2.1.1 子過程
給定左上角和右下角兩個點,可以確定一個矩形。
打印上邊的邊:
打印右邊的邊:
打印下邊的邊:
打印左邊的邊:
2.1.2 整體分析
一層一層打印,第一層打完,由左上角和右下角移動后,分別確定下一層的范圍:
2.2 代碼實現(xiàn)
package Solution;public class PrintMatrix {public static void main(String[] args) {int[][] matrix= {{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16},{17,18,19,20}};int[][] ma1= {{1,2,3,4}};int[][] ma2= {{1},{2},{3},{4}};printMatrix(matrix);System.out.println();printMatrix(ma1);System.out.println();printMatrix(ma2);}public static void printMatrix(int[][] matrix) {int hstart=0;int hend=0;int lstart=matrix.length-1;//行數(shù)int lend=matrix[0].length-1;//列數(shù)while(hstart<=lstart&&hend<=lend) {printEdge(matrix,hstart++,hend++,lstart--,lend--);}}public static void printEdge(int[][] ma,int hs,int he,int ls,int le) {if(hs==ls)while(he<=le)System.out.print(ma[hs][he++]+" ");else if(he==le)while(hs<=ls)System.out.print(ma[hs++][he]+" ");else {int curC=hs;//當(dāng)前行標(biāo)int curR=he;//當(dāng)前列標(biāo)while(curR<le) System.out.print(ma[curC][curR++]+" ");while(curC<ls)System.out.print(ma[curC++][curR]+" ");while(curR>he) System.out.print(ma[curC][curR--]+" ");while(curC>hs)System.out.print(ma[curC--][curR]+" ");}} }運行結(jié)果:
3.旋轉(zhuǎn)正方形矩陣
【題目】 給定一個整型正方形矩陣matrix, 請把該矩陣調(diào)整成順時針旋轉(zhuǎn)90度的樣子。
【要求】 額外空間復(fù)雜度為O(1)。
3.1 分析
分層轉(zhuǎn)。如下,分成兩層:
第一層:
拿出1放到4的位置,4放到16的位置,16放到13的位置,13放到1的位置;
接著:
第一層中的2放到8的位置,8放到15的位置,15放到9的位置,9放到2的位置;
3,5,12,14類似。
第二層也一樣。
3.2 代碼實現(xiàn)
package Solution;public class RotateMatrix {public static void main(String[] args) {int[][] matrix= {{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};int hstart=0;int hend=0;int lstart=matrix.length-1;int lend=matrix[0].length-1;while(hstart<=lstart)rotateMatrix(matrix,hstart++,hend++,lstart--,lend--);for(int i=0;i<matrix.length;i++) {for(int j=0;j<matrix[0].length;j++)System.out.print(matrix[i][j]+" ");System.out.println();}}public static void rotateMatrix(int[][] ma,int hs,int he,int ls,int le) {int times=le-he;for(int i=0;i<times;i++){int temp=ma[hs][he+i];ma[hs][he+i]=ma[ls-i][he];ma[ls-i][he]=ma[ls][le-i];ma[ls][le-i]=ma[hs+i][le];ma[hs+i][le]=temp; }} }運行結(jié)果:
注意:代碼中times的使用。
int times=le-he;
- 即每行元素的個數(shù)-1
- 每一列第一個元素加到最后一個元素所需加的次數(shù)
- 但是不能到最后一個元素,所以循環(huán)的i應(yīng)小于times。到達最后一個元素的前一個元素就可停止。
4.反轉(zhuǎn)單向和雙向鏈表
【題目】 分別實現(xiàn)反轉(zhuǎn)單向鏈表和反轉(zhuǎn)雙向鏈表的函數(shù)。
【要求】 如果鏈表長度為N, 時間復(fù)雜度要求為O(N), 額外空間復(fù)雜度要求為O(1)。
4.1 反轉(zhuǎn)單鏈表
4.1.1 分析
反轉(zhuǎn)之前:
需要設(shè)置兩個指針pre、next,next指向當(dāng)前節(jié)點的后繼(以確定當(dāng)前節(jié)點的下一個節(jié)點的位置),pre指向當(dāng)前節(jié)點的前驅(qū)(以確定當(dāng)前節(jié)店反轉(zhuǎn)之后的后繼)。head指向的是當(dāng)前節(jié)點。
Node pre=null; Node next=head.next;首先,令當(dāng)前節(jié)點的后繼指向pre所指的節(jié)點(此處為null,反轉(zhuǎn)之后1為末節(jié)點,所以他的后繼本應(yīng)也就為null):
head.next=pre;然后,令pre指向head,以保存2節(jié)點反轉(zhuǎn)之后的后繼節(jié)點位置:
pre=head;接著,head移到它的后繼位置,繼續(xù)處理下一個節(jié)點(節(jié)點2):
head=next;一輪結(jié)束!
第二輪:
代碼:
next=head.next; head.next=pre; pre=head; head=next;圖示:
4.1.2 代碼實現(xiàn)
package Solution;class Node {public int value;public Node next;public Node(int data) {this.value = data;} }public class ReverseList {public static void main(String[] args) {Node head=new Node(1);head.next=new Node(2);head.next.next=new Node(3);printList(head);Node revhead=reverseList(head);printList(revhead);}public static Node reverseList(Node head) {//head不為空Node pre=null;Node next=null;while(head!=null) {next=head.next;head.next=pre;pre=head;head=next;}return pre;}public static void printList(Node head) {while(head!=null) {System.out.print(head.value+" ");head=head.next;}System.out.println();}}運行結(jié)果:
4.2 反轉(zhuǎn)雙向鏈表
4.2.1 分析
同樣準(zhǔn)備兩個指針pre、next:
步驟和反轉(zhuǎn)單向鏈表一樣:
代碼:
next=head.next; head.next=pre; head.last=next; pre=head; head=next;圖示:
4.2.2 代碼實現(xiàn)
package Solution;class DoubleNode {public int value;public DoubleNode last;public DoubleNode next;public DoubleNode(int data) {this.value = data;} } public class ReverseDoubleList {public static void main(String[] args) {DoubleNode head2 = new DoubleNode(1);head2.next = new DoubleNode(2);head2.next.last = head2;head2.next.next = new DoubleNode(3);head2.next.next.last = head2.next;head2.next.next.next = new DoubleNode(4);head2.next.next.next.last = head2.next.next;printDoubleList(head2);printDoubleList(reverseDoubleList(head2));}public static DoubleNode reverseDoubleList(DoubleNode head) {DoubleNode next=null;DoubleNode pre=null;while(head!=null) {next=head.next;head.next=pre;head.last=next;pre=head;head=next;}return pre;}public static void printDoubleList(DoubleNode head) {System.out.print("Double Linked List: ");DoubleNode end = null;while (head != null) {System.out.print(head.value + " ");end = head;head = head.next;}System.out.print("| ");while (end != null) {System.out.print(end.value + " ");end = end.last;}System.out.println();} }運行結(jié)果:
5.求n的加法組合,將一個整數(shù)拆分成多個整數(shù)相加的形式, O(N)時間,O(N)空間
原博
?
總結(jié)
以上是生活随笔為你收集整理的算法练习day8——190326(猫狗队列、转圈打印矩阵、旋转正方形矩阵、反转单向双向链表、数N的加法组合)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 算法练习day7——190325(比较器
- 下一篇: 算法练习day8——190326(队列实