剑指offer算法题JZ16-JZ20
题库链接(牛客网)
JZ16 合并两个排序的链表
描述
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
示例1
输入:{1,3,5},{2,4,6}
返回值:{1,2,3,4,5,6}
测试代码(java)
public class JZ16 {
public static void main(String[] args) {
ListNode l1 = new ListNode(1);
ListNode l2 = new ListNode(3);
ListNode l3 = new ListNode(5);
l1.next = l2;
l2.next = l3;
ListNode l4 = new ListNode(2);
ListNode l5 = new ListNode(4);
ListNode l6 = new ListNode(6);
l4.next = l5;
l5.next = l6;
ListNode l = Merge(l1,l4);
while (l != null){
System.out.print(l.val + " ");
l = l.next;
}
}
public static ListNode Merge(ListNode list1,ListNode list2) {
ListNode l = new ListNode(-1);
ListNode head = l;
if (list1 == null){
return list2;
} else if (list2 == null){
return list1;
}
while (list1 != null && list2 != null){
if (list1.val <= list2.val){
l.next = list1;
list1 = list1.next;
} else {
l.next = list2;
list2 = list2.next;
}
l = l.next;
}
if (list1 == null){
l.next = list2;
} else {
l.next = list1;
}
return head.next;
}
}
JZ17 树的子结构
描述
输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
示例1
输入:{8,8,#,9,#,2,#,5},{8,9,#,2}
返回值:true
测试代码(java)
public class JZ17 {
public static void main(String[] args) {
TreeNode x1 = new TreeNode(8);
TreeNode x2 = new TreeNode(8);
TreeNode x3 = new TreeNode(9);
TreeNode x4 = new TreeNode(2);
TreeNode x5 = new TreeNode(5);
x1.left = x2;
x2.left = x3;
x3.left = x4;
x4.left = x5;
x1.preOut();
System.out.println();
TreeNode y1 = new TreeNode(8);
TreeNode y2 = new TreeNode(9);
TreeNode y3 = new TreeNode(2);
y1.left = y2;
y2.left = y3;
y1.preOut();
System.out.println(HasSubtree(x1,y1));
}
public static boolean HasSubtree(TreeNode root1,TreeNode root2) {
if (root1 == null || root2 == null){
return false;
}
return equals(root1,root2) || HasSubtree(root1.right,root2) || HasSubtree(root1.left,root2);
}
public static boolean equals(TreeNode root1,TreeNode root2){
if (root2 == null){
return true;
} else if (root1 == null || root1.val != root2.val){
return false;
} else {
return equals(root1.left,root2.left) && equals(root1.right,root2.right);
}
}
}
JZ18 二叉树的镜像
描述
操作给定的二叉树,将其变换为源二叉树的镜像。
比如: 源二叉树
8
/ \
6 10
/ \ / \
5 7 9 11
镜像二叉树
8
/ \
10 6
/ \ / \
11 9 7 5
示例1
输入:{8,6,10,5,7,9,11}
返回值:{8,10,6,11,9,7,5}
测试代码(java)
public class JZ18 {
public static void main(String[] args) {
TreeNode l1 = new TreeNode(8);
TreeNode l2 = new TreeNode(6);
TreeNode l3 = new TreeNode(10);
TreeNode l4 = new TreeNode(5);
TreeNode l5 = new TreeNode(7);
TreeNode l6 = new TreeNode(9);
TreeNode l7 = new TreeNode(11);
l1.left = l2;
l1.right = l3;
l2.left = l4;
l2.right = l5;
l3.left = l6;
l3.right = l7;
TreeNode s = Mirror(l1);
System.out.println(s.left.val);
}
public static TreeNode Mirror (TreeNode pRoot) {
// write code here
if (pRoot == null){
return null;
}
TreeNode r = Mirror(pRoot.right);
TreeNode l = Mirror(pRoot.left);
pRoot.left = r;
pRoot.right = l;
return pRoot;
}
}
JZ19 顺时针打印矩阵
描述
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下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]
示例1
输入:[[1,2],[3,4]]
返回值:[1,2,4,3]
思路解析
纯逻辑题,没有多难,参数比较多,特别是二维数组的行列别搞混了
测试代码(java)
import java.util.ArrayList;
public class JZ19 {
public static void main(String[] args) {
int[][] m1= {{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
ArrayList<Integer> arrayList1 = printMatrix(m1);
System.out.println(arrayList1.toString());
int[][] m2 = {{1},{5},{9},{13}};
ArrayList<Integer> arrayList2= printMatrix(m2);
System.out.println(arrayList2.toString());
}
public static ArrayList<Integer> printMatrix(int [][] matrix) {
ArrayList<Integer> arrayList = new ArrayList<>();
int x1 = 0;
// 纵向最大长度
int x2 = matrix.length;
int y1 = 0;
// 横向最大长度
int y2 = 0;
if (x2 != 0){
y2 = matrix[0].length;
}
// 运动模式
int num = 0;
int x = x1;
int y = y1;
while (x1<x2 && y1<y2){
arrayList.add(matrix[x][y]);
// 上右
if (num == 0){
if (y < y2-1){
y++;
} else {
num = 1;
x1++;
x++;
}
}
// 右下
else if (num == 1){
if (x < x2-1){
x++;
} else {
num = 2;
y2--;
y--;
}
}
// 下左
else if (num == 2){
if (y > y1){
y--;
} else {
num = 3;
x2--;
x--;
}
}
// 左上
else {
if (x > x1){
x--;
} else {
num = 0;
y1++;
y++;
}
}
}
return arrayList;
}
}
JZ20 包含min函数的栈
描述
定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数,并且调用 min函数、push函数 及 pop函数 的时间复杂度都是 O(1)
push(value):将value压入栈中
pop():弹出栈顶元素
top():获取栈顶元素
min():获取栈中最小元素
示例:
输入: [“PSH-1”,“PSH2”,“MIN”,“TOP”,“POP”,“PSH1”,“TOP”,“MIN”]
输出: -1,2,1,-1
解析:
"PSH-1"表示将-1压入栈中,栈中元素为-1
"PSH2"表示将2压入栈中,栈中元素为2,-1
“MIN”表示获取此时栈中最小元素==>返回-1
"TOP"表示获取栈顶元素==>返回2
"POP"表示弹出栈顶元素,弹出2,栈中元素为-1
"PSH-1"表示将1压入栈中,栈中元素为1,-1
"TOP"表示获取栈顶元素==>返回1
“MIN”表示获取此时栈中最小元素==>返回-1
示例1
输入: ["PSH-1","PSH2","MIN","TOP","POP","PSH1","TOP","MIN"]
返回值:-1,2,1,-1
测试代码(java)(非最佳解,比较耗时)
import java.util.Stack;
public class JZ20 {
static Stack<Integer> stack1 = new Stack<Integer>();
public static void main(String[] args) {
push(-1);
push(2);
System.out.println(min());
System.out.println(top());
pop();
push(1);
System.out.println(top());
System.out.println(min());
}
public static void push(int node) {
stack1.push(node);
}
public static void pop() {
stack1.pop();
}
public static int top() {
return stack1.peek();
}
public static int min() {
Stack<Integer> stack2 = new Stack<Integer>();
int b = stack1.pop();
stack2.push(b);
while (!stack1.isEmpty()){
int a = stack1.pop();
if (a < b){
b = a;
}
stack2.push(a);
}
while (!stack2.isEmpty()){
stack1.push(stack2.pop());
}
return b;
}
}