文章目录
1.转圈打印矩阵
给定一个整型矩阵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)。
思路;始终确定两个点。没有打印框中的左上角的点和右下角的点。然后直到这两个点重合的时候,那么这个矩阵就打印完成了。
//其中aR,aC:代表左上角的行和列。bR和bC:代表的是右下角的行和列。
public class e08zhuanquan_print {
public static void spiralOrderPrint(int[][] matrix){
if(matrix==null||matrix.length==0||matrix.length==1&&matrix[0].length==0){
throw new RuntimeException(“矩阵为空”);
}
int aR=0;
int aC=0;
int bR=matrix.length-1;
int bC=matrix[0].length-1;
while (aR<=bR&&aC<=bC){
printedge(matrix,aR++,aC++,bR--,bC--);
}
}
public static void printedge(int[][] m,int aR,int aC,int bR,int bC){
if (aR==bR){
for (int i=aC;i<=bC;i++){
System.out.println(m[aR][i]+" ");
}
}
else if (aC==bC){
for (int i=aR;i<=bR;i++){
System.out.println(m[i][aC]+" ");
}
}else{
int curC=aC;
int curR=aR;
while(curC!=bC){
System.out.println(m[aR][curC]);
curC++;
}
while(curR!=bR){
System.out.println(m[curR][bC]);
curR++;
}
while(curC!=aC){
System.out.println(m[bR][curC]);
curC--;
}
while (curR!=aR){
System.out.println(m[curR][aC]);
curR--;
}
}
}
public static void main(String[] args) {
int[][] m={{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
spiralOrderPrint(m);
}
}
2:旋转90度打印正方形矩阵
给定一个整型正方形矩阵matrix,请把该矩阵调整成 顺时针旋转90度的样子。 【要求】 额外空间复杂度为O(1)。
思路:因为我们要旋转打印,所以首先将原数组中相应的位置进行交换,成最后的样子的数组,然后在依次打印该数组。
注意:这种交换位置的操作,始终都是先降低一个位置给temp,然后倒序来赋值。这样就能实现交换的操作。
public class e09rotate {
public static void rotate(int[][] matrix){
int aR=0;
int aC=0;
int bR=matrix.length-1;
int bC=matrix[0].length-1;
while(aR<bR){
rotateEdge(matrix,aR++,aC++,bR--,bC--);
}
printMatrix(matrix);
}
//依次交换位置。到最终需要实现的数组。
public static void rotateEdge(int[][] m,int aR,int aC,int bR,int bC){
int times=bC-aC; //需要旋转的次数。
int tmp=0;
for (int i=0;i<times;i++){
tmp=m[aR][aC+i]; //后者:4个点中的第一个点
m[aR][aC+i]=m[bR-i][aC]; //后者:4个点中的最后一个点。
m[bR-i][aC]=m[bR][bC-i]; //后者:4个点的第三个点
m[bR][bC-i]=m[aR+i][bC]; //后者:4个点的第2个点。
m[aR+i][bC]=tmp;
}
}
public static void printMatrix(int[][] m){
for (int i=0;i<m.length;i++){
for (int j=0;j<m[0].length;j++){
System.out.print(m[i][j]+" ");
}
System.out.println();
}
}
public static void main(String[] args) {
int[][] m={{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
rotate(m);
}
}
3.z字形(之字形 )打印举证
思路:每次的打印都以A和B的位置为参考,但是每次打印:(1)如果是从上往下打印,以a为起点。(2)如果是从下往上打印,以b为起点。
public class e10ZigZagPrintMatrix {
public static void printMatrixZigZag(int[][] matrix){
int aR=0;
int aC=0;
int bR=0;
int bC=0;
int EndR=matrix.length-1;
int EndC=matrix[0].length-1;
boolean fromUp=false;
while(aR!=EndR+1){ //a来到最后一行,因为a和b是同时到达最后一行的。
printLevel(matrix,aR,aC,bR,bC,fromUp);
aR= aC==EndC?aR+1:aR; //只有a的列数来到最后一列,a的行数才增加
aC= aC==EndC?aC:aC+1;
bC= bR==EndR?bC+1:bC;
bR= bR==EndR?bR:bR+1; //上面的四行,就是a和b分别移动到下一个位置。
fromUp=!fromUp;
}
}
public static void printLevel(int[][] m,int aR,int aC,int bR,int bC,boolean fromUp){
if (fromUp){
while (aR<bR+1){ //等价于while(ar<=br)
System.out.print(m[aR++][aC--]+" "); //从上往下打印,以a为起点
}
}else{
while(bR>bR-1){ //等价于while(br>=ar )
System.out.print(m[bR--][bC++]+" "); //从下往上打印,以b为起点。
}
}
}
public static void main(String[] args) {
int[][] matrix = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } };
printMatrixZigZag(matrix);
}
}
4.在行列都排好序的矩阵中找数
思路:从右上角(或者从左小角)出发,如果当前值比k大,就往左走,比k小,往下走。
public class e11FindNumInSortedMatrix {
public static boolean isContains(int[][] matrix,int K){
int row=0;
int col=matrix[0].length-1;
while(row<matrix.length&&col>=0){
if(matrix[row][col]==K){
return true;
}else if (matrix[row][col]>K){
col--;
}else{
row++;
}
}
return false;
}
public static void main(String[] args) {
int[][] matrix = new int[][] { { 0, 1, 2, 3, 4, 5, 6 },// 0
{ 10, 12, 13, 15, 16, 17, 18 },// 1
{ 23, 24, 25, 26, 27, 28, 29 },// 2
{ 44, 45, 46, 47, 48, 49, 50 },// 3
{ 65, 66, 67, 68, 69, 70, 71 },// 4
{ 96, 97, 98, 99, 100, 111, 122 },// 5
{ 166, 176, 186, 187, 190, 195, 200 },// 6
{ 233, 243, 321, 341, 356, 370, 380 } // 7
};
int K = 234;
System.out.println(isContains(matrix, K));
}
}
5.打印两个链表的公共部分
给定两个有序链表的头指针 head1 和 head2 ,打印两个链表的公共部分
public class e11PrintCommonPart {
public static class Node {
public int value;
public Node next;
public Node(int data) {
this.value = data;
}
}
public static void printCommonPart(Node head1, Node head2) {
while (head1 != null && head2 != null) {
if (head1.value < head2.value) {
head1 = head1.next;
} else if (head1.value > head2.value) {
head2 = head2.next;
} else {
System.out.print(head1.value+" ");
head1 = head1.next;
head2 = head2.next;
}
}
System.out.println();
}
public static void printLinkedList(Node head){
System.out.print("LinkedList: ");
while (head!=null){
System.out.print(head.value+" ");
head=head.next;
}
System.out.println();
}
public static void main(String[] args) {
Node node1 = new Node(2);
node1.next = new Node(3);
node1.next.next = new Node(5);
node1.next.next.next = new Node(6);
Node node2 = new Node(1);
node2.next = new Node(2);
node2.next.next = new Node(5);
node2.next.next.next = new Node(7);
node2.next.next.next.next = new Node(8);
printLinkedList(node1);
printLinkedList(node2);
printCommonPart(node1, node2);
}
}
6.判断链表是否是回文结构。
思路:使用栈,先将链表压入栈中,然后从栈中弹出来,然后与原链表依次比较。
import java.util.Stack;
public class e12IsPalindromeList {
// need n extra space
public static boolean isPalindrome1(Node head) {
Node cur=head;
Stack<Node> s=new Stack<>();
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;
}
//need n/2 extra space
public static boolean isPalindrome2(Node head){
if(head==null||head.next==null){
return true;
}
Node cur=head;
Node right=head.next;
Stack<Node> s=new Stack<>();
while(cur.next!=null&&cur.next.next!=null){
cur=cur.next.next;
right=right.next;
}
while(right!=null){
s.push(right);
right=right.next;
}
while(!s.isEmpty()){
if(s.pop().value!=head.value){
return false;
}
head=head.next;
}
return true;
}
}
7.将单向链表按某值划分成左边小、中间相等、右边大的形式
【题目】 给定一个单向链表的头节点head,节点的值类型是整型,再给定一个整数pivot。实现一个调整链表的函数,将链表调整为左部分都是值小于 pivot的节点,中间部分都是值等于pivot的节点,右部分都是值大于 pivot的节点。除这个要求外,对调整后的节点顺序没有更多的要求。 例如:链表9->0->4->5->1,pivot=3
。 调整后链表可以是1->0->4->9->5
,也可以是0->1->9->5->4
。总之,满 足左部分都是小于3的节点,中间部分都是等于3的节点(本例中这个部分为空),右部分都是大于3的节点即可。对某部分内部的节点顺序不做要求。
思路:方案1:将链表全部压入到数组中,然后使用荷兰国旗问题去解决。(但是这种快排的方式不能解决稳定性。)
方案2:
注意:在最后3个链表相连接的时候,只需要考虑相连处的前一个链表为不为空的情况,此题为前两个链表。因为在最后返回的值的时候考虑了为空的情况
public class e13SmallerEqualBigger {
public static Node listPartition1(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
while(head!=null){
Node 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?sT:eT; //这步其实就在判断equal位置,是否为空,如果为空将eT指向sT那么就会直接跳过中间这个链表。
}
//all reconnect
if (eT!=null){
eT.next=bH;
}
return sH!=null?sH:eH!=null?eH:bH;
}
public static void printLinkedList(Node head){
System.out.println("Linked LIst: ");
while(head!=null){
System.out.print(head.value+" ");
head=head.next;
}
System.out.println();
}
public static void main(String[] args) {
Node head1 = new Node(7);
head1.next = new Node(9);
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(2);
head1.next.next.next.next.next.next = new Node(5);
printLinkedList(head1);
// head1 = listPartition1(head1, 4);
head1 = listPartition1(head1, 5);
printLinkedList(head1);
}
}