java打印回文矩阵_双指针问题“转圈打印矩阵”+“之字型打印矩阵”+“在行列都排好序的矩阵中找数”+“回文问题”...

转圈打印矩阵:

【题目】 给定一个整型矩阵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)。

【思路】

模拟剥洋葱式输出,将矩阵从外围一圈一圈往里逼近。

设定两个标记位置,一个为矩阵的左上角边界,一个为矩阵的右下角边界,第一圈,从左上角的点开始按顺时针横坐标++打印元素,一直到右下角边界点的横坐标则停,然后纵坐标++往下打印元素,一直到右下角边界点的纵坐标则停,然后横坐标减减打印元素,一直到左上角边界点的横坐标则停,然后纵坐标减减输出打印,一直到与左上角边界点的纵坐标相等时不打印。此时即将外面一圈按转圈的方式打印完毕,然后更新左右边界,将左上角边界横纵坐标都++,右下角边界点横纵坐标都--,重复上述转圈打印,即可。

81bfdd65da96df7cc3c9dd4f4349d6bb.png

【Code】

public static void spiralOrderPrint(int[][] matrix) {int tR = 0;//左上角坐标int tC = 0;int dR = matrix.length - 1;//右下角坐标int dC = matrix[0].length - 1;while (tR <= dR && tC <=dC) {

printEdge(matrix, tR++, tC++, dR--, dC--);

}

}public static void printEdge(int[][] m, int tR, int tC, int dR, intdC) {if (tR ==dR) {for (int i = tC; i <= dC; i++) {

System.out.print(m[tR][i]+ " ");

}

}else if (tC ==dC) {for (int i = tR; i <= dR; i++) {

System.out.print(m[i][tC]+ " ");

}

}else{int curC =tC;int curR =tR;while (curC !=dC) {

System.out.print(m[tR][curC]+ " ");

curC++;

}while (curR !=dR) {

System.out.print(m[curR][dC]+ " ");

curR++;

}while (curC !=tC) {

System.out.print(m[dR][curC]+ " ");

curC--;

}while (curR !=tR) {

System.out.print(m[curR][tC]+ " ");

curR--;

}

}

}public static voidmain(String[] args) {int[][] matrix = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12},

{13, 14, 15, 16} };

spiralOrderPrint(matrix);

}

“之”字形打印矩阵:

【题目】 给定一个矩阵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)。

【思路】

设定两个点,初始位置都为(0,0),打印第一个元素后,a点往右移一步,b点往下移一步,两点之间形成一条对角线,打印对角线上的元素,规定方向,一开始为右上往左下,随后为左下往右上打印,打印完毕后两点继续右移和下移,当a点右移到边界时下移,b点下移到边界时右移,ab两点总能形成一条对角线,交替方向打印对角线上的数据即可。

【Code】

public static void printMatrixZigZag(int[][] matrix) {int tR = 0;int tC = 0;int dR = 0;int dC = 0;int endR = matrix.length - 1;int endC = matrix[0].length - 1;boolean fromUp = false;while (tR != endR + 1) {

printLevel(matrix, tR, tC, dR, dC, fromUp);

tR= tC == endC ? tR + 1: tR;

tC= tC == endC ? tC : tC + 1;

dC= dR == endR ? dC + 1: dC;

dR= dR == endR ? dR : dR + 1;

fromUp= !fromUp;

}

System.out.println();

}public static void printLevel(int[][] m, int tR, int tC, int dR, intdC,booleanf) {if(f) {while (tR != dR + 1) {

System.out.print(m[tR++][tC--] + " ");

}

}else{while (dR != tR - 1) {

System.out.print(m[dR--][dC++] + " ");

}

}

}

在行列都排好序的矩阵中找数:

【题目】

给定一个有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)。

【思路】

依题意,起始先从矩阵的右上角开始查找,如果比K大,证明此点下方所有元素都比K大,不用再看,将位置左移,比较,若还是比K大,则证明此点下方所有元素也都比K大,不用再看,将位置左移,比较,若此时该位置比K小,但不等于K,则往下查,如又比K大,则左移,如比K小,则下移,直至查到,或到达矩阵边界,程序结束。

【Code】

public static boolean isContains(int[][] matrix, intK) {int row = 0;int col = matrix[0].length - 1;while (row < matrix.length && col > -1) {if (matrix[row][col] ==K) {return true;

}else if (matrix[row][col] >K) {

col--;

}else{

row++;

}

}return false;

}

判断一个链表是否为回文结构:

【题目】

给定一个链表的头节点head,请判断该链表是否为回文结构。

例如:

1->2->1,返回true。

1->2->2->1,返回true。

15->6->15,返回true。

1->2->3,返回false。

附:查找链表中点位置,需要一个快指针和一个慢指针,快指针一次走两步,慢指针一次走1步,当快指针到达终点时慢指针即在链表的中点位置。

【基本思路】

使用一个栈结构,将数据都压入栈内,然后一一出栈与数组从头开始比较即可判别。

public static booleanisPalindrome1(Node head) {

Stack stack = new Stack();

Node cur=head;while (cur != null) {

stack.push(cur);

cur=cur.next;

}while (head != null) {if (head.value !=stack.pop().value) {return false;

}

head=head.next;

}return true;

}

进阶:

如果链表长度为N,时间复杂度达到O(N),额外空间复杂度达到O(1)。

【思路1】(省一半空间复杂度)

使用附中技术,找到链表中点,将中点后的元素都压入栈中,再依次从表头开始对出栈元素进行比较。

public static booleanisPalindrome2(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 stack = new Stack();while (right != null) {

stack.push(right);

right=right.next;

}while (!stack.isEmpty()) {if (head.value !=stack.pop().value) {return false;

}

head=head.next;

}return true;

}

【思路2】(空间复杂度为O(1)但实现较繁琐复杂,适合面试讲述)

还是用附的技术找到链表中点,此时将中点往后的元素进行逆序。然后从两头开始进行比对。

比如1->2->3->2->1,找到中点3,将3后的链表逆序,改成1->2->3

逆序操作:例将3->2->1逆序,将2的next指针1记下,将2指向3,然后下顺,将1的next指针记下,再将next指向2。具体实现看Code。

【Code】

//need O(1) extra space

public static booleanisPalindrome3(Node head) {if (head == null || head.next == null) {return true;

}

Node n1=head;

Node n2=head;while (n2.next != null && n2.next.next != null) { //find mid node

n1 = n1.next; //n1 -> mid

n2 = n2.next.next; //n2 -> end

}

n2= n1.next; //n2 -> right part first node

n1.next = null; //mid.next -> null

Node n3 = null;while (n2 != null) { //right part convert

n3 = n2.next; //n3 -> save next node

n2.next = n1; //next of right node convert

n1 = n2; //n1 move

n2 = n3; //n2 move

}

n3= n1; //n3 -> save last node

n2 = head;//n2 -> left first node

boolean res = true;while (n1 != null && n2 != null) { //check palindrome

if (n1.value !=n2.value) {

res= false;break;

}

n1= n1.next; //left to mid

n2 = n2.next; //right to mid

}

n1=n3.next;

n3.next= null;while (n1 != null) { //recover list

n2 =n1.next;

n1.next=n3;

n3=n1;

n1=n2;

}returnres;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值