16 合并两个链表
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
有两种方法:一种是递归,一种是非递归
public class mergeTwoList_16 {
public static void main(String[] args) {
link4 l1 = new link4();
link4 l2 = new link4();
for(int i = 0; i <= 7; i++) {
l1.add(i);
l2.add(i+3);
}
mergeTwoList_16 merge = new mergeTwoList_16();
ListNode4 node = merge.Merge2(l1.root, l2.root);
while(node != null) {
System.out.print(node.val+" ");
node = node.next;
}
}
//递归版本
public ListNode4 Merge(ListNode4 l1,ListNode4 l2) {
if(l1 == null) {
return l2;
}
if(l2 == null) {
return l1;
}
if(l1.val <= l2.val) {
l1.next = Merge(l1.next, l2);
return l1;
}else {
l2.next =Merge(l1, l2.next);
return l2;
}
}
//非递归
public ListNode4 Merge2(ListNode4 l1,ListNode4 l2) {
ListNode4 pre = new ListNode4(-1);
ListNode4 cur =pre;
while(l1 != null && l2 != null) {
if(l1.val <= l2.val) {
cur.next = l1;
l1 = l1.next;
}else {
cur.next = l2;
l2 = l2.next;
}
cur = cur.next;
}
if(l1 != null) cur.next = l1;
if(l2 != null) cur.next = l2;
return pre.next;
}
}
class link4{
ListNode4 root;
public void add(int val) {
ListNode4 listNode = new ListNode4(val);
if(this.root == null) {
this.root = listNode;
}else {
this.root.add(listNode);
}
}
}
class ListNode4{
int val;
ListNode4 next;
public ListNode4(int val) {
this.val = val;
}
public void add(ListNode4 listNode) {
if(this.next == null) {
this.next = listNode;
}else {
this.next.add(listNode);
}
}
}
17 树的子结构
输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
基本思路就是遍历大树,找到与子结构跟节点相同的节点,然后传入判断函数进行遍历比较
public class substructureOfTree_17 {
public static void main(String[] args) {
substructureOfTree_17 s = new substructureOfTree_17();
TreeNode2 root1 = new TreeNode2(1);
TreeNode2 node1 = new TreeNode2(2);
TreeNode2 node2 = new TreeNode2(3);
TreeNode2 node3 = new TreeNode2(4);
TreeNode2 node4 = new TreeNode2(5);
TreeNode2 root2 = new TreeNode2(2);
TreeNode2 node5 = new TreeNode2(4);
TreeNode2 node6 = new TreeNode2(5);
root1.left = node1;
root1.right = node2;
node1.left = node3;
node1.right = node4;
root2.left = node5;
root2.right = node6;
boolean flag = s.HasSubtree(root1, root2);
System.out.println(flag);
}
//遍历大树
public boolean HasSubtree(TreeNode2 root1,TreeNode2 root2) {
//当Tree1和Tree2都不为零的时候,才进行比较。否则直接返回false
if(root1 == null || root2 == null) {
return false;
}
//如果找到与子树相同根的值
if(root1.val == root2.val) {
//以这个根节点为为起点判断是否包含Tree2
if(judge(root1,root2)) {
return true;
}
}
//如果找不到,那么就再去root的左儿子或者右儿子当作起点,去判断时候包含Tree2
return HasSubtree(root1.left, root2) || HasSubtree(root1.right, root2);
}
public boolean judge(TreeNode2 node1,TreeNode2 node2) {
//如果Tree2已经遍历完了都能对应的上,返回true
if(node2 == null) {
return true;
}
//如果Tree2还没有遍历完,Tree1却遍历完了。返回false
//这两段判断代码不能交换位置
if(node1 == null) {
return false;
}
//如果其中有一个点没有对应上,返回false
if(node1.val != node2.val) {
return false;
}
//如果根节点对应的上,那么就分别去子节点里面匹配
return judge(node1.left,node2.left) && judge(node1.right,node2.right) ;
}
}
class TreeNode2{
int val;
TreeNode2 left;
TreeNode2 right;
public TreeNode2(int val) {
this.val = val;
}
}
18 二叉树的镜像
操作给定的二叉树,将其变换为源二叉树的镜像。
两种方法:递归与非递归
递归:交换左右子树的节点,然后递归调用该方法。
非递归:借助队列
import java.util.LinkedList;
import java.util.Queue;
public class mirror_18 {
public static void main(String[] args) {
mirror_18 mirror = new mirror_18();
TreeNode3 root = new TreeNode3(8);
TreeNode3 node1 = new TreeNode3(6);
TreeNode3 node2 = new TreeNode3(10);
TreeNode3 node3 = new TreeNode3(5);
TreeNode3 node4 = new TreeNode3(7);
TreeNode3 node5 = new TreeNode3(9);
TreeNode3 node6 = new TreeNode3(11);
root.left = node1;
root.right = node2;
node1.left = node3;
node1.right = node4;
node2.left = node5;
node2.right = node6;
mirror.Mirror2(root);
root.preOrder();
}
//递归
public void Mirror(TreeNode3 root) {
if(root == null) {
return;
}
TreeNode3 temp = root.left;
root.left = root.right;
root.right = temp;
Mirror(root.left);
Mirror(root.right);
}
//非递归
public void Mirror2(TreeNode3 root) {
Queue<TreeNode3> queue = new LinkedList<>();
TreeNode3 temp ,cur;
queue.offer(root);
int len = queue.size();
for(int i = 0; i < len; i++) {
cur = queue.poll();
temp = cur.left;
cur.left = cur.right;
cur.right = temp;
if(cur.left != null) queue.offer(cur.left);
if(cur.left != null) queue.offer(cur.right);
len = queue.size();
}
}
}
class TreeNode3{
int val;
TreeNode3 left;
TreeNode3 right;
public TreeNode3(int val) {
this.val = val;
}
public void preOrder() {
System.out.print(this.val+" ");
if(this.left != null) {
this.left.preOrder();
}
if(this.right != null) {
this.right.preOrder();
}
}
}
19 顺时针打印矩阵
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 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.
分析
简单来说,就是不断地收缩矩阵的边界
定义四个变量代表范围,up、down、left、right
- 向右走存入整行的值,当存入后,该行再也不会被遍历,代表上边界的 up 加一,同时判断是否和代表下边界的 down 交错
- 向下走存入整列的值,当存入后,该列再也不会被遍历,代表右边界的 right 减一,同时判断是否和代表左边界的 left 交错
- 向左走存入整行的值,当存入后,该行再也不会被遍历,代表下边界的 down 减一,同时判断是否和代表上边界的 up 交错
- 向上走存入整列的值,当存入后,该列再也不会被遍历,代表左边界的 left 加一,同时判断是否和代表右边界的 right 交错
import java.util.ArrayList;
public class clockwisePrintMatrix_19 {
public static void main(String[] args) {
int[][] matrix = {{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
clockwisePrintMatrix_19 print = new clockwisePrintMatrix_19();
ArrayList<Integer> res = print.printMatrix(matrix);
System.out.println(res.toString());
}
public ArrayList<Integer> printMatrix(int [][] matrix) {
ArrayList<Integer> list = new ArrayList<Integer> ();
if(matrix == null) {
return list;
}
int up = 0;
int down = matrix.length-1;
int left = 0;
int right = matrix[0].length-1;
while(true) {
//最上面一行
for(int col = left; col <= right; col++) {
list.add(matrix[up][col]);
}
//向下逼近
up++;
//判断是否越界
if(up > down) {
break;
}
//最右边一行
for(int row = up; row <= down ;row++) {
list.add(matrix[row][right]);
}
//向左逼近
right--;
//判断是否越界
if(left > right) {
break;
}
//最下面以一行
for(int col = right; col >= left; col--) {
list.add(matrix[down][col]);
}
//向上逼近
down--;
//判断是否越界
if(up > down) {
break;
}
//最左边一行
for(int row = down; row >= up ;row--) {
list.add(matrix[row][left]);
}
//向右逼近
left++;
//判断是否越界
if(left > right) {
break;
}
}
return list;
}
}
20 栈的压入、弹出
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)序列