剑指Offer题目JAVA版思路与代码(五)

11 篇文章 0 订阅
6 篇文章 0 订阅

第十五题:反转链表
题目描述:
输入一个链表,反转链表后,输出链表的所有元素。
思路:
这里写图片描述
由于在做指针反转的过程中,对于结点i,需要知道它前一个结点h来作为反转后的下一个结点,以及后一个结点j来继续推进。
代码:

/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
    public ListNode ReverseList(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        ListNode p1 = null;
        ListNode p2 = head;
        ListNode p3 = head.next;
        while (p3 != null) {
            p2.next = p1;
            p1 = p2;
            p2 = p3;
            p3 = p3.next;
        }
        p2.next = p1;
        return p2;
    }
}

第十六题:合并两个排序的链表
题目描述:
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
思路:
需要两个指针,分别指向两个链表的要比较的那个结点,比较大小后指向下一个结点,要注意的是比较完之后多余的链表结点要加在新链表后面。当然这个题目可以用递归的思路解决。
代码:

/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
    public ListNode Merge(ListNode list1,ListNode list2) {
        if (list1 == null) {
            return list2;
        }
        if (list2 == null) {
            return list1;
        }
        ListNode ret = null;
        if (list1.val <= list2.val) {
            ret = list1;
            ret.next = Merge(list1.next, list2);
        } else {
            ret = list2;
            ret.next = Merge(list1, list2.next);
        }
        return ret;
    }
}

第十七题:树的子结构
题目描述:
输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
思路:
先比较AB两树的根结点是否相同,相同的基础上进一步比较AB树的子结点是否相同。遍历的方式采用递归的方法。
代码:

/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;
    }
}
*/
public class Solution {
    public boolean HasSubtree(TreeNode root1,TreeNode root2) {
        if(root2 == null || root1 == null) {
            return false;
        }
        boolean ret = false;
        if (root1.val == root2.val) {
            ret = IsSubtree(root1, root2);
        }
        if (!ret) {
            ret = HasSubtree(root1.left, root2);
        }
        if (!ret) {
            ret = HasSubtree(root1.right, root2);
        }
        return ret;
    }
    public boolean IsSubtree(TreeNode root1, TreeNode root2) {
        if (root2 == null) {
            return true;
        }
        if (root1 == null) {
            return false;
        }
        if (root1.val == root2.val){
            return IsSubtree(root1.left, root2.left) && IsSubtree(root1.right, root2.right);
        }else {
            return false;
        }
    }
}

第十八题:二叉树的镜像
题目描述:
操作给定的二叉树,将其变换为原二叉树的镜像。
思路:
对跟结点而言,只要它的左右儿子不都为null,则交换它的左右结点,并且递归这个过程。
代码:

/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;
    public TreeNode(int val) {
        this.val = val;
    }
}
*/
public class Solution {
    public void Mirror(TreeNode root) {
        if (root == null ||
           (root.left == null && root.right == null)) {
            return ;
        }
        TreeNode tmp = root.left;
        root.left = root.right;
        root.right = tmp;
        Mirror(root.left);
        Mirror(root.right);
    }
}

第十九题:顺时针打印矩阵
题目描述:
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵: 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.
思路:
这个题目需要具体在纸上画一下,其实每一圈的起始点的行列坐标时相同的,即(0,0)-》(1,1)-》(2,2)-》(n,n);其背后的规律就是每一圈能打印的前提就是这个行数大于2n,并且列数大于2n。要注意的是每一圈的打印,除了每一圈的第一行一定可以打印以外,其余的都需要判断是否符合条件。具体看代码。
代码:

import java.util.ArrayList;
public class Solution {
    ArrayList<Integer> ret = new ArrayList<>();
    public ArrayList<Integer> printMatrix(int [][] matrix) {
        if (matrix == null || matrix.length <=0 ||
            matrix[0].length <= 0) {
            return ret;
        }
        int index = 0;
        int rows = matrix.length;
        int columns = matrix[0].length;
        while ((rows > 2 * index) && (columns > 2 * index)) {
            print(matrix, index);
            index ++;
        }
        return ret;
    }
    public void print(int [][] matrix, int index){
        int endX = matrix[0].length - 1 - index;
        int endY = matrix.length - 1 - index;
        //第一行放进去
        for (int i = index; i <= endX; i++) {
            ret.add(matrix[index][i]);
        }
        //最后一列
        if (endY > index) {
            for (int i = index+1; i <= endY; i++) {
                ret.add(matrix[i][endX]);
            }
        }
        //最后一行
        if (endY>index && endX > index) {
            for (int i = endX-1; i >= index; i--) {
                ret.add(matrix[endY][i]);
            }
        }
        //第一列
        if (endX > index && endY > index+1) {
            for (int i = endY-1; i > index; i--) {
                ret.add(matrix[i][index]);
            }
        }
    }
}

第二十题:包含min函数的栈
题目描述:
定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数。
思路:
需要一个辅助栈min,每次让数据栈里面放数据时,先判断min中前一个数字a与放入的数字b的大小,如果b小,则往min中压入b,如果a小,则往min中再一次压入a;这个辅助栈的数据个数与数据栈的数据个数一样,保证了在提取当前栈的最小值时能后以o(1) 的时间复杂度找到。
代码:

import java.util.Stack;

public class Solution {
    Stack<Integer> data = new Stack<Integer>();
    Stack<Integer> min = new Stack<Integer>();
    public void push(int node) {
        data.push(node);
        if(!min.isEmpty() && min.peek()<=node) {
            min.push(min.peek());
        }else{
            min.push(node);
        }
    }

    public void pop() {
        if((!data.isEmpty())&&(!min.isEmpty())) {
            data.pop();
            min.pop();
        }
    }

    public int top() {
        if((!data.isEmpty())&&(!min.isEmpty())) {
            return data.peek();
        }else{
            return -1;
        }
    }

    public int min() {
        if((!data.isEmpty())&&(!min.isEmpty())) {
            return min.peek();
        }else {
            return -1;
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值