隊列例子node
貓狗隊列數組
寵物、狗和貓的類以下:數據結構
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"); } }
實現一種狗貓隊列的結構,要求以下:函數
用戶能夠調用add方法將cat類或dog類的 實例放入隊列中;oop
用戶能夠調用pollAll方法,將隊列中全部的實例按照進隊列 的前後順序依次彈出;ui
用戶能夠調用pollDog方法,將隊列中dog類的實例按照 進隊列的前後順序依次彈出;this
用戶能夠調用pollCat方法,將隊列中cat類的實 例按照進隊列的前後順序依次彈出;spa
用戶能夠調用isEmpty方法,檢查隊列中是 否還有dog或cat的實例;指針
用戶能夠調用isDogEmpty方法,檢查隊列中是否有dog 類的實例;code
用戶能夠調用isCatEmpty方法,檢查隊列中是否有cat類的實例。
public class DogCatQueue { public static class Pet { private String type; public Pet(String type) { this.type = type; } public String getPetType() { return this.type; } } public static class Dog extends Pet { public Dog() { super("dog"); } } public static class Cat extends Pet { public Cat() { super("cat"); } } public static class PetEnterQueue { private Pet pet; private long count; public PetEnterQueue(Pet pet, long count) { this.pet = pet; this.count = count; } public Pet getPet() { return this.pet; } public long getCount() { return this.count; } public String getEnterPetType() { return this.pet.getPetType(); } } public static class AnimalQueue{ private Queue<PetEnterQueue> dogQ; private Queue<PetEnterQueue> catQ; private long count; public AnimalQueue() { this.dogQ = new LinkedList<PetEnterQueue>(); this.catQ = new LinkedList<PetEnterQueue>(); this.count = 0; } public void add(Pet pet) { if (pet.getPetType().equals("dog")) { this.dogQ.add(new PetEnterQueue(pet, this.count++)); } else if (pet.getPetType().equals("cat")) { this.catQ.add(new PetEnterQueue(pet, this.count++)); } else { throw new RuntimeException("err, not dog or cat"); } } public Pet pollAll() { if (!this.dogQ.isEmpty() && !this.catQ.isEmpty()) { if (this.dogQ.peek().getCount() < this.catQ.peek().getCount()) { return this.dogQ.poll().getPet(); } else { return this.catQ.poll().getPet(); } } else if (!this.dogQ.isEmpty()) { return this.dogQ.poll().getPet(); } else if (!this.catQ.isEmpty()) { return this.catQ.poll().getPet(); } else { throw new RuntimeException("err, queue is empty!"); } } public Dog pollDog() { if (!this.isDogQueueEmpty()) { return (Dog) this.dogQ.poll().getPet(); } else { throw new RuntimeException("Dog queue is empty!"); } } public Cat pollCat() { if (!this.isCatQueueEmpty()) { return (Cat) this.catQ.poll().getPet(); } else throw new RuntimeException("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(); } } }
轉圈打印矩陣
【題目】 給定一個整型矩陣matrix,請按照轉圈的方式打印它。
例如: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
打印結果爲:1,2,3,4,8,12,16,15,14,13,9, 5,6,7,11, 10
【要求】 額外空間複雜度爲O(1)
/*找最左上和最右下方兩個座標,調用函數遍歷打印 * 而後座標不斷往中心移動,繼續調用函數遍歷打印 * ,直到座標相遇,橫縱相遇都算, * */ public static void findEdge(int[][] matrix){ int lx=0; int ly=0; int rx=matrix.length-1; int ry=matrix[0].length-1; while(lx<=rx&&ly<=ry){ printEdge(matrix,lx++,ly++,rx--,ry--); } } private static void printEdge(int[][] matrix, int lx, int ly, int rx, int ry) { //行相遇,從左到右打印 if(lx==rx){ for(int i=ly;i<=ry;i++){ System.out.print(matrix[lx][i]+" "); } } //列相遇,從上到下打印 else if(ly==ry){ for(int i=lx;i<=rx;i++){ System.out.print(matrix[i][ly]+" "); } }else{ int curx=lx; int cury=ly; //左——>右 while(cury!=ry){ System.out.print(matrix[lx][cury++]+" "); } //上——>下 while(curx!=rx){ System.out.print(matrix[curx++][ry]+" "); } //右——>左 while(cury!=ly){ System.out.print(matrix[rx][cury--]+" "); } //下——>上 while(curx!=lx){ System.out.print(matrix[curx--][ly]+" "); } } }
旋轉正方形矩陣
給定一個整型正方形矩陣matrix,請把該矩陣調整成 順時針旋轉90度的樣子。
【要求】 額外空間複雜度爲O(1)
public static void rotate(int[][] matrix){ int lx=0; int ly=0; int rx=matrix.length-1; int ry=matrix[0].length-1; while(lx<rx){ rotateEdge(matrix,lx++,ly++,rx--,ry--); } } private static void rotateEdge(int[][] matrix, int lx, int ly, int rx, int ry) { int temp=0; for(int i=0;i!=rx-lx;i++){ temp=matrix[lx][ly+i]; matrix[lx][ly+i]=matrix[rx-i][ly]; matrix[rx-i][ly]=matrix[rx][ry-i]; matrix[rx][ry-i]=matrix[lx+i][ry]; matrix[lx+i][ry]=temp; } }
「之」字形打印矩陣
給定一個矩陣matrix,按照「之」字形的方式打印這 個矩陣。
例如: 1 2 3 4 5 6 7 8 9 10 11 12。
「之」字形打印的結果爲:1,2,5,9,6,3,4,7,10,11, 8,12。
【要求】 額外空間複雜度爲O(1)。
/*定義兩個座標啊a,b * a先向右移,移到最右後向下移,移到最下角中止 * b先向下移,移到最下後向右移,移到最下角中止 * 這樣兩個座標就能夠連城對角線,座標就是兩個邊界,遍歷線上的數便可 * */ public static void findEdge(int[][] matrix){ int ax=0; int ay=0; int bx=0; int by=0; int endX=matrix.length-1; int endY=matrix[0].length-1; boolean flag=false; //當座標a移到最下角時中止 while (ax!=endX+1){ print(matrix,ax,ay,bx,by,flag); ax=ay==endY?ax+1:ax; ay=ay==endY?ay:ay+1; //這裏要先給by賦值,由於下面的操做會影響bx的值 by=bx==endX?by+1:by; bx=bx==endX?bx:bx+1; flag=!flag; } } private static void print(int[][] matrix, int ax, int ay, int bx, int by, boolean flag) { if(flag){ //右上——左下 while(ax!=bx+1){ System.out.print(matrix[ax++][ay--]+" "); } }else{ //左下——右上 while(bx!=ax-1){ System.out.print(matrix[bx--][by++]+" "); } } }
在行列都排好序的矩陣中找數
給定一個有N*M的整型矩陣matrix和一個整數K, matrix的每一行和每一 列都是排好序的。實現一個函數,判斷K 是否在matrix中。
例如:
0 1 2 5
2 3 4 7
4 4 4 8
5 7 7 9
若是K爲7,返回true;若是K爲6,返 回false。
【要求】 時間複雜度爲O(N+M),額外空間複雜度爲O(1)。
public static boolean isContains(int[][] matrix,int num){ /*起點定在右上角 * 根據比較數的大小,來進行左移或者下移 * 若是相等,直接返回true * 若是查的數比num大,左移,這個數下面的數排掉,由於確定比num大 * 若是查的數比num小,下移,這個數左邊的數排掉,由於確定比num小 * * */ int row=0; int col=matrix[0].length-1; while(row<matrix.length&&col>-1){ if(matrix[row][col]==num){ return true; }else if(matrix[row][col]>num){ col--; }else{ row++; } } return false; }
單向鏈表反轉
public class ReverseList { //實現單向鏈表 public static class Node{ public int value; public Node next; public Node(int data){ this.value=data; } } //反轉單向鏈表 public static Node reverseList(Node 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 printLinkedList(Node head){ while (head!=null){ System.out.print(head.value+" "); head=head.next; } System.out.println(); } public static void main(String[] args) { Node n=new Node(1); n.next=new Node(2); n.next.next=new Node(3); printLinkedList(n); n=reverseList(n); printLinkedList(n); } }
判斷一個鏈表是否爲迴文結構
給定一個鏈表的頭節點head,請判斷該鏈表是否爲回 文結構。
例如:
1->2->1,返回true。
1->2->2->1,返回true。
15->6->15,返回true。
1->2->3,返回false。
public class isHuiWenList { public static class Node{ public int value; public Node next; public Node(int data){ this.value=data; } } //方法1,空間複雜度n //利用棧來存儲,再進行比較 public static boolean isHuiWen1(Node head){ Stack<Node> s=new Stack<Node>(); Node cur=head; while(cur!=null){ s.push(cur); cur=cur.next; } while (head!=null){ if(head.value!=s.pop().value){ return false; } head=head.next; } return true; } //方法2,空間複雜度n/2 //定義兩個快慢指針,當cur走完時,right恰好走到中間,進行壓棧,出棧比較 public static boolean isHuiWen2(Node head){ if(head==null||head.next==null) return true; Node right=head.next; Node cur=head; while(cur.next!=null&&cur.next.next!=null){ right=right.next; cur=cur.next.next; } Stack<Node> s=new Stack<Node>(); while(right!=null){ s.push(right); right=right.next; } while(!s.isEmpty()){ if(head.value!=s.pop().value){ return false; } head=head.next; } return true; } //方法3,空間複雜度1 //定義兩個快慢指針, public static boolean isHuiWen3(Node head){ if(head==null||head.next==null) return true; Node n1=head;//慢指針 Node n2=head;//快指針 while(n2.next!=null&&n2.next.next!=null){ n1=n1.next;//中止時在中間 n2=n2.next.next;//中止時在末尾 } n2=n1.next;//右半部分第一個結點 n1.next=null;//mid.next->null Node n3=null; while(n2!=null){//右半部分反轉 n3=n2.next;//保留下一個結點 n2.next=n1;//當前結點指向前面結點 n1=n2;//前面結點設置爲當前結點 n2=n3;//當前結點設置爲下一個結點 } n3=n1;//保留最後的結點 n2=head;//保留第一個結點 boolean res=true; while (n1!=null&&n2!=null){ if(n1.value!=n2.value){ res=false; break; } n1=n1.next; n2=n2.next; } n1=n3.next; n3.next=null; while(n1!=null){//後半部分反轉回來 n2=n1.next;//保留下一個結點 n1.next=n3;//下個結點指向當前結點 n3=n1;//下個結點設置爲當前結點 n1=n2;//當前結點設置爲下個結點 } return res; } public static void main(String[] args) { Node n=new Node(1); n.next=new Node(2); n.next.next=new Node(3); System.out.println(isHuiWen3(n)); } }
將單向鏈表按某值劃分紅左邊小、中間相等、右邊大的形式
給定一個單向鏈表的頭節點head,節點的值類型是整型,再給定一個 整 數pivot。實現一個調整鏈表的函數,將鏈表調整爲左部分都是值小於 pivot 的節點,中間部分都是值等於pivot的節點,右部分都是值大於 pivot的節點。在左、中、右三個部分的內部也作順序要求,要求每部分裏的節點從左 到右的 順序與原鏈表中節點的前後次序一致。
例如:鏈表9->0->4->5->1,pivot=3。 調整後的鏈表是0->1->9->4->5。 在知足原問題要求的同時,左部分節點從左到 右爲0、1。在原鏈表中也 是先出現0,後出現1;中間部分在本例中爲空,再也不 討論;右部分節點 從左到右爲九、四、5。在原鏈表中也是先出現9,而後出現4, 最後出現5。
若是鏈表長度爲N,時間複雜度請達到O(N),額外空間複雜度請達到O(1)。
public class HeLanGQ { public static class Node { public int value; public Node next; public Node(int data) { this.value = data; } } //方法1 //遍歷鏈表,把鏈表的結點存進數組,對數組操做,而後再拼成鏈表返回 public static Node listPartition1(Node head, int pivot) { if (head == null) { return head; } Node cur = head; int i = 0; while (cur != null) { i++; cur = cur.next; } Node[] nodeArr = new Node[i]; i = 0; cur = head; for (i = 0; i != nodeArr.length; i++) { nodeArr[i] = cur; cur = cur.next; } arrPartition(nodeArr, pivot); for (i = 1; i != nodeArr.length; i++) { nodeArr[i - 1].next = nodeArr[i]; } nodeArr[i - 1].next = null; return nodeArr[0]; } public static void arrPartition(Node[] nodeArr, int pivot) { int small = -1; int big = nodeArr.length; int index = 0; while (index != big) { if (nodeArr[index].value < pivot) { swap(nodeArr, ++small, index++); } else if (nodeArr[index].value == pivot) { index++; } else { swap(nodeArr, --big, index); } } } public static void swap(Node[] nodeArr, int a, int b) { Node tmp = nodeArr[a]; nodeArr[a] = nodeArr[b]; nodeArr[b] = tmp; } //方法2 //把鏈表分紅三個小鏈表,小的放第一個,相等放第二個,大的放最後,每一個鏈表記錄頭和尾,後面進行拼接。 public static Node listPartition2(Node head, int pivot) { Node sH = null; // small head Node sT = null; // small tail Node eH = null; // equal head Node eT = null; // equal tail Node bH = null; // big head Node bT = null; // big tail Node next = null; // save next node // every node distributed to three lists while (head != null) { next = head.next; head.next = null; if (head.value < pivot) { if (sH == null) { sH = head; sT = head; } else { sT.next = head; sT = head; } } else if (head.value == pivot) { if (eH == null) { eH = head; eT = head; } else { eT.next = head; eT = head; } } else { if (bH == null) { bH = head; bT = head; } else { bT.next = head; bT = head; } } head = next; } // small and equal reconnect if (sT != null) { sT.next = eH;//小鏈表尾指向中鏈表頭 eT = eT == null ? bH : eT;//判斷中鏈表是否爲空 } // all reconnect if (eT != null) { eT.next = bH;//中鏈表尾指向大鏈表頭 } return sH != null ? sH : eH != null ? eH : bH; } public static void printLinkedList(Node node) { System.out.print("Linked List: "); while (node != null) { System.out.print(node.value + " "); node = node.next; } System.out.println(); } public static void main(String[] args) { Node head1 = new Node(7); head1.next = new Node(3); head1.next.next = new Node(1); head1.next.next.next = new Node(8); head1.next.next.next.next = new Node(5); head1.next.next.next.next.next = new Node(5); head1.next.next.next.next.next.next = new Node(9); printLinkedList(head1); //head1 = listPartition1(head1, 5); head1 = listPartition2(head1, 5); printLinkedList(head1); } }
複製含有隨機指針節點的鏈表
一種特殊的鏈表節點類描述以下:
public class Node {
public int value;
public Node next;
public Node rand;
public Node(int data) { this.value = data; }
}
Node類中的value是節點值,next指針和正常單鏈表中next指針的意義 一 樣,都指向下一個節點,rand指針是Node類中新增的指針,這個指 針可 能指向鏈表中的任意一個節點,也可能指向null。 給定一個由 Node節點類型組成的無環單鏈表的頭節點head,請實現一個 函數完成 這個鏈表中全部結構的複製,並返回複製的新鏈表的頭節點。 進階: 不使用額外的數據結構,只用有限幾個變量,且在時間複雜度爲 O(N) 內完成原問題要實現的函數。
方法1:藉助輔助空間
public static Node copyListWithRand1(Node head){ HashMap<Node,Node> map=new HashMap<Node,Node>(); Node cur=head; while (cur!=null){ map.put(cur,new Node(cur.value)); cur=cur.next; } cur=head; while(cur!=null){ map.get(cur.value).next=map.get(cur.next); map.get(cur.value).rand=map.get(cur.rand); cur=cur.next; } return map.get(head); }
方法2:不借助輔助空間
public static Node copyListWithRand2(Node head) { if (head == null) { return null; } Node cur = head; Node next = null; // copy node and link to every node while (cur != null) { next = cur.next; cur.next = new Node(cur.value); cur.next.next = next; cur = next; } cur = head; Node curCopy = null; // set copy node rand while (cur != null) { next = cur.next.next; curCopy = cur.next; curCopy.rand = cur.rand != null ? cur.rand.next : null; cur = next; } Node res = head.next; cur = head; // split while (cur != null) { next = cur.next.next; curCopy = cur.next; cur.next = next; curCopy.next = next != null ? next.next : null; cur = next; } return res; }
兩個單鏈表相交的一系列問題
在本題中,單鏈表可能有環,也可能無環。給定兩個 單鏈表的頭節點 head1和head2,這兩個鏈表可能相交,也可能 不相交。請實現一個函數, 若是兩個鏈表相交,請返回相交的 第一個節點;若是不相交,返回null 便可。
要求:若是鏈表1 的長度爲N,鏈表2的長度爲M,時間複雜度請達到 O(N+M),額外 空間複雜度請達到O(1)。
//主要方法 public static Node getIntersectNode(Node head1, Node head2) { if (head1 == null || head2 == null) { return null; } Node loop1 = getLoopNode(head1);//判斷鏈表是否有環 Node loop2 = getLoopNode(head2);//判斷鏈表是否有環 if (loop1 == null && loop2 == null) {//兩個鏈表都無環 return noLoop(head1, head2); } if (loop1 != null && loop2 != null) {//兩個鏈表都有環 return bothLoop(head1, loop1, head2, loop2); } return null; } //定義快慢指針,當兩個指針相遇時,快指針回到原點,快指針變爲慢指針,再次相遇時,即爲第一次相遇點 public static Node getLoopNode(Node head) { if (head == null || head.next == null || head.next.next == null) { return null; } Node n1 = head.next; // n1 -> slow Node n2 = head.next.next; // n2 -> fast while (n1 != n2) { if (n2.next == null || n2.next.next == null) { return null; } n2 = n2.next.next; n1 = n1.next; } n2 = head; // n2 -> walk again from head while (n1 != n2) { n1 = n1.next; n2 = n2.next; } return n1; } public static Node noLoop(Node head1, Node head2) { if (head1 == null || head2 == null) { return null; } Node cur1 = head1; Node cur2 = head2; int n = 0;//記錄兩個鏈表的長度差值 while (cur1.next != null) { n++; cur1 = cur1.next; } while (cur2.next != null) { n--; cur2 = cur2.next; } //最後一個結點不相等,不可能相交 if (cur1 != cur2) { return null; } cur1 = n > 0 ? head1 : head2; cur2 = cur1 == head1 ? head2 : head1; n = Math.abs(n); while (n != 0) { n--; cur1 = cur1.next; } while (cur1 != cur2) { cur1 = cur1.next; cur2 = cur2.next; } return cur1; } //兩種狀況 public static Node bothLoop(Node head1, Node loop1, Node head2, Node loop2) { Node cur1 = null; Node cur2 = null; if (loop1 == loop2) { cur1 = head1; cur2 = head2; int n = 0; while (cur1 != loop1) { n++; cur1 = cur1.next; } while (cur2 != loop2) { n--; cur2 = cur2.next; } cur1 = n > 0 ? head1 : head2; cur2 = cur1 == head1 ? head2 : head1; n = Math.abs(n); while (n != 0) { n--; cur1 = cur1.next; } while (cur1 != cur2) { cur1 = cur1.next; cur2 = cur2.next; } return cur1; } else { cur1 = loop1.next; while (cur1 != loop1) { if (cur1 == loop2) { return loop1; } cur1 = cur1.next; } return null; } }