剑指offer系列
第一题
二叉搜索树后序遍历序列
题目描述
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。
核心思路:
二叉搜索树 ,左< 中 < 右, 后序遍历序列为 :【左,右,中】,
处理方法: 找到根节点,比较左树和右树先对根节点的关系
也就是说推出矛盾点,如果 右边的树比根要小,或者左边的树比根要大,那就不满足后序遍历序列的规律
这里使用 非递归的方法遍历这个序列
因为最右边的节点一定是根节点
关键点是:深刻理解二叉搜索树的结构的规律
我们把叶子节点也看成是一颗二叉树,也就是说 子节点为null的一颗二叉树
后序遍历后,从右向左一个一个地选择节点,其前面总会有两段连续的序列
左边序列每个数总是比 root 要小,右边序列每个数总是比root要大,当然左右两序列的长度是不一样的
具体怎么就解释不清了,看代码: 我每轮循环都从最有端选一个节点作为根节点
public class Solution {
public boolean VerifySquenceOfBST(int [] sequence) {
if(0==sequence.length) return false;
//后序: 左 右 根 , 根部最小,右边最大
//矛盾点, 如果 左边比 根节点要大,右边的树比根节点要小,就是错,关键:确定根节点
return handleRoot(sequence);
}
public boolean handleRoot(int[] arr)
{
int root = arr.length-1;
int i=0;
while(root>0)
{
while(arr[i]<arr[root]) i++;
while(arr[i]>arr[root]) i++;
if(i<root--) return false;
i=0;
}
return true;
}
}
第二题
回溯算法水题
题目描述
输入一颗二叉树的根节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。(注意: 在返回值的list中,数组长度大的数组靠前)
必备模板
public class Solution {
private int target;
private ArrayList<ArrayList<Integer>> ans = new ArrayList();
public ArrayList<ArrayList<Integer>> FindPath(TreeNode root,int target) {
this.target = target;
this.ans.clear();
if(root!=null)
dfs(root,new ArrayList<Integer>(),0);
return ans;
}
public void dfs(TreeNode root,ArrayList<Integer> path,int sum) {
path.add(root.val);sum+=root.val;
if(root.left==null&&root.right==null&&sum==this.target) {
ans.add(new ArrayList<Integer>(path));
}
if(root.left!=null) dfs(root.left,path,sum);
if(root.right!=null) dfs(root.right,path,sum);
path.remove(path.size()-1);
}
}
第三题
图论算法题目
复制链表
题目描述
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
这个题我有写过一篇文章,在LeetCode上有一样的题,再刷一遍
import java.util.HashMap;
public class Solution {
public RandomListNode Clone(RandomListNode pHead)
{
if(pHead==null) return pHead;
HashMap<RandomListNode,RandomListNode> check = new HashMap();
RandomListNode begin = pHead;
RandomListNode ans = pHead;
while(begin!=null) {
check.put(begin,new RandomListNode(begin.label));
begin = begin.next;
}
while(pHead!=null)
{
RandomListNode cur = check.get(pHead);
cur.next = check.get(pHead.next);
cur.random = check.get(pHead.random);
pHead = pHead.next;
}
return check.get(ans);
}
}
思路:先把模子准备好,后面就穿针引线
输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
import java.util.ArrayList;
import java.util.Collections;
public class Solution {
public ArrayList<String> Permutation(String str) {
ArrayList<String> res = new ArrayList();
if(str!=null&&str.length()>0) handle(res,str.toCharArray(),0);
Collections.sort(res);
return res;
}
public void handle(ArrayList<String> res,char[] arr,int i) {
if(i==arr.length-1)
{
String val = String.valueOf(arr);
if(!res.contains(val))
{
res.add(val);
}
}else{
for(int j=i;j<arr.length;++j)
{
swap(arr,i,j);
handle(res,arr,i+1);
swap(arr,i,j);
}
}
}
public void swap(char[] arr,int i,int j){
char t = arr[i];
arr[i]=arr[j];
arr[j]=t;
}
}
使用回溯算法,重点刷题
下一题
二叉搜索树与双向链表
题目描述
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
思路:将二叉树中序遍历,存储在一个队列中,然后再调整指针即可
二叉搜索树中序遍历一定是有序数组
import java.util.Stack;
import java.util.LinkedList;
import java.util.Queue;
class Solution{
public TreeNode Convert(TreeNode pRootOfTree) {
if (pRootOfTree == null) {
return null;
}
return convert(pRootOfTree);
}
private TreeNode convert(TreeNode root) {
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
LinkedList<TreeNode> queue = new LinkedList<>();
while (cur != null || !stack.isEmpty()) {
while (cur != null) {
stack.push(cur);
cur = cur.left;
}
if (!stack.isEmpty()) {
cur = stack.pop();
queue.offer(cur);
cur = cur.right;
}
}
TreeNode ans = queue.pollFirst();
TreeNode begin = ans;
begin.left =null;
for(TreeNode t:queue)
{
begin.right = t;
t.left = begin;
begin=begin.right;
}
begin.right=null;
return ans;
}
}
或者
import java.util.Stack;
import java.util.LinkedList;
import java.util.Queue;
class Solution{
public TreeNode Convert(TreeNode pRootOfTree) {
if (pRootOfTree == null) {
return null;
}
return convert(pRootOfTree);
}
private TreeNode convert(TreeNode root) {
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
Queue<TreeNode> queue = new LinkedList<>();
while (cur != null || !stack.isEmpty()) {
while (cur != null) {
stack.push(cur);
cur = cur.left;
}
if (!stack.isEmpty()) {
cur = stack.pop();
queue.offer(cur);
cur = cur.right;
}
}
TreeNode ans = queue.poll();
TreeNode begin = ans;
begin.left =null;
while(!queue.isEmpty())
{
TreeNode t = queue.poll();
begin.right=t;
t.left=begin;
begin=begin.right;
}
begin.right=null;
return ans;
}
}