剑指offer(java)—— 字符串、链表、树、栈和队列

字符串

面试题5:替换空格

题目:请实现一个函数将一个字符串中的每个空格替换成 ““%20”。 例如当字符串为 We Are Happy。则经过替换之后的字符串为 We%20Are%20Happy。
分析:利用 StringBuffer的字符添加功能

代码实现

public class Solution{
    public String replaceSpace(StringBuffer str) {
        String s = new String(str);
        char[] chars = s.toCharArray();
        StringBuffer buffer = new StringBuffer();
        for(int i = 0; i < chars.lenght; i++) {
            if(chars[i] == 32) {
                buffer.append("%20");
            }elset {
                buffer.append(chars[i]);
            }
        }
        return buffer.toString();
    }
}

链表

面试题6:从尾到头打印链表

题目:输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。
分析:遍历的顺序是从头到尾,输出的顺序是从尾到头,即第一个遍历的节点最后一个输出,而最后一个遍历到的节点第一个输出,这是典型的“先进后出”。因此可以利用栈的思想来实现这种顺序。

代码实现

import java.util.ArrayList;
import java.util.Stack;
public class Solution{
    public static ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
        ArrayList<Integer> array = new ArrayList<Integer>();
        Stack<ListNode> stack = new Stack<ListNode>();
        ListNode current = listNode;
    
        while(current != null) {
            stack.push(current);
            current = current.next;
        }
        while(!stack.isEmpty()) {
            array.add(stack.pop().val);
        }
        return array;
    }
}

面试题7:重建二叉树

题目:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列 {1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
分析
前序遍历:根结点—> 左子树 —> 右子树
中序遍历:左子树—> 根结点 —> 右子树
后序遍历:左子树—> 右子树 —> 根结点
层次遍历:只需按层次遍历即可
前序遍历的第一个值就是根结点的值,扫描中序遍历就能确定根结点的位置。在根结点前面的值是左子树结点的值,后面的是右子树结点的值。而对于左子树来说,前序遍历的第二个值是左子树的子结点,因此可以在中序遍历中确定左子结点的位置。采用递归实现。

代码实现

import java.util.HashMap;
public class Solution{
    public static TreeNode reConstructBinaryTree(int[] pre, int[] in) {
        if(pre == null || in == null) {
            return null;
        }
        HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
        for(int i = 0; i < in.length - 1; i++) {
            map.put(in[i], i);
        }
        return preIn(pre, 0, pre.length - 1, in, 0, in.length - 1, map);
    }

    public static TreeNode preIn(int[] pre, int startPre, int endPre, int[] in, 
                                 int startIn, int endIn, HashMap<Integer, Integer> map {
        if(startPre < endPre) {
            return null;
        }
        TreeNode head = new TreeNode(pre[startPre]);   //存入根结点
        int index = map.get(pre[startPre]);     //找到根结点在中序遍历中的位置
        head.left = preIn(pre, startPre + 1, startPre + index - startIn, in, startIn, index - 1, map);
        head.right = preIn(pre, start + index - startIn - 1, endPre, in, index + 1, endIn, map);
        return head;
    }
}

面试题8:二叉树的下一个节点

题目:给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针
分析:中序遍历:左子树 —> 根结点 —> 右子树
在这里插入图片描述
如果一个结点有右子树,那么该结点的下一个结点就是它的右子树中的最左子结点,例如a的下一结点为f。也就是说从右子结点出发一直沿着指向左子结点的指针,就能找到它的下一个结点。如果一个结点没有右子树,即该结点是它父结点 的左子结点,那么它的下一个结点就是它的父结点。
如果一个结点既没有右子树,并且它还是它父结点的右子结点 ,这种情况就比较复杂。我们可以沿着指向父结点的指针一直向上遍历,直到找到一个是它父结点的左子结点的结点。如果这样的结点存在,那么这个结点的父结点就是我们要找的下一个结点。

代码实现

public class Solution {
    public static TreeLinkNode GetNext(TreeLinkNode pNode) {
        if(pNode == null) {
            return null;
        }
        
        TreeLinkNode pNext = null;
        if(pNode.right != null) {
            TreeLinkNode pRight = pNode.right;    //右子树
            while(pRight.left != null) {
                pRight = pRight.left;         //找到右子树的最左子结点
            }
            pNext = pRight;
        }else if(pNode.next != null) {
            TreeLinkNode pCurrent = pNode;
            TreeLinkNode pParent = pNode.next;
            //当前结点是父结点的右子结点
            while(pParent != null  && pCurrent == pParent.right) {
                pCurrent = pParent;
                pParent = pParent.next;   //向上遍历,找到一个是它父结点的左子结点的结点
            }
            pNext = pParent;
        }
        return pNext;
    }
}

栈和队列

面试题9:用两个栈实现队列

题目:用两个栈来实现一个队列,完成队列的Push和 Pop操作。 队列中的元素为 int类型。
分析:队列是一种先进先出的数据结构,而栈是先进后出的一种形式。

Stack()创建一个空的栈
void push(T s)往栈中添加一个新的元素
T pop()移除并返回最新添加的元素
boolean isEmpty()栈是否为空
int size()栈的大小

队列的push()操作,就是直接在stack1上进行栈的push()操作;
队列的pop()操作就是得到stack1最底下的那个元素,先把stack1的元素逐个退出放入到stack2中,当stack1中的元素为空时,stack2的栈顶元素就是所要的元素。在该元素返回前,将剩余元素返回至stack1中。

代码实现

import java.util.Stack;
public class Solution{
    Stack<Integer> stack1 = new Stack<Integer>();
    Stack<Integer> stack2 = new Stack<Integer>();

    public void push(int node) {
        stack1.push(node);
    }
    
    public void pop() {
        while(!stack.isEmpty()) {
            stack2.push(stack1.pop());
        }
        Integer result = stack2.pop();
        while(!stack2.isEmpty()) {
            stack1.push(stack2.pop());
        }
        return result;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值