剑指Offer编程题(5)二叉树中和为某一值的路径

1. 二叉树中和为某一值的路径

题目描述

输入一颗二叉树的根节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。(注意: 在返回值的list中,数组长度大的数组靠前).

分析

  • 经典的递归策略
  • 定义一个ArrayList集合paths存放ArrayList集合path,path为值为所求和的路径
  • 编写方法find求出符合的路径,参数有两个集合,一个节点,一个需要的和
  • 先把当前节点的值加到path集合里,接着判断最后的值是不是当前节点的值

代码

import java.util.ArrayList;
/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
  public ArrayList> FindPath(TreeNode root,int target) {
    ArrayList> paths = new ArrayList>();
    if(root==null)return paths;
    find(paths,new ArrayList(),root,target);
    return paths;
  }
  public void find(ArrayList> paths,ArrayList path,TreeNode root,int target) {
    path.add(root.val);
    if(root.left==null&&root.right==null){
      if(target==root.val){
        paths.add(path);
      }
      return;
    }
    ArrayList path2 = new ArrayList();
    path2.addAll(path);
    if(root.left!=null)find(paths,path,root.left,target-root.val);
    if(root.right!=null)find(paths,path2,root.right,target-root.val);
  }
}

2. 复杂链表的复制

题目描述

输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)

分析

原文连接

解题思路:

  • 遍历链表,复制每个结点,如复制结点A得到A1,将结点A1插到结点A后面;
  • 重新遍历链表,复制老结点的随机指针给新结点,如A1.random = A.random.next;
  • 拆分链表,将链表拆分为原链表和复制后的链表


代码

/*
public class RandomListNode {
    int label;
    RandomListNode next = null;
    RandomListNode random = null;

    RandomListNode(int label) {
        this.label = label;
    }
}
*/
public class Solution {
  public RandomListNode Clone(RandomListNode pHead)
  {
    if(pHead == null){
      return null;
    }
    RandomListNode currentNode = pHead;
    //1.复制每个节点,如复制A得到A1,将节点A1查到节点A后面
    while(currentNode != null){
      RandomListNode cloneNode = new RandomListNode(currentNode.label);
      RandomListNode nextNode = currentNode.next;
      currentNode.next = cloneNode;
      cloneNode.next = nextNode;
      currentNode = nextNode;
    }
    //2.重新遍历链表,复制老节点的随机指针给新节点如A1.random = A.random.next;
    currentNode = pHead;
    while(currentNode != null){
      currentNode.next.random = currentNode.random==null?null:currentNode.random.next;
      currentNode = currentNode.next.next;
    }
    //拆分链表
    currentNode = pHead;
    RandomListNode pCloneHead = pHead.next;
    while(currentNode != null){
      RandomListNode cloneNode = currentNode.next;
      currentNode.next = cloneNode.next;
      cloneNode.next = cloneNode.next == null?null:cloneNode.next.next;
      currentNode = currentNode.next;
    }
    return pCloneHead;
  }
}

3. 二叉搜索树与双向链表

题目描述

输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。

分析

1.核心是中序遍历的非递归算法。

2.修改当前遍历节点与前一遍历节点的指针指向。

代码

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

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
import java.util.Stack;
public class Solution {
  public TreeNode Convert(TreeNode pRootOfTree) {
    if(pRootOfTree==null){
      return null;
    }
    Stack stack = new Stack();
    TreeNode p = pRootOfTree;
    TreeNode pre = null;//用于保存中序遍历的上一节点
    boolean isFirst = true;
    while(p!=null||!stack.isEmpty()){
      while(p!=null){
        stack.push(p);
        p = p.left;
      }
      p = stack.pop();
      if(isFirst){
        pRootOfTree = p;//将中序遍历的第一个节点记为root
        pre = pRootOfTree;
        isFirst = false;
      }else{
        pre.right = p;
        p.left = pre;
        pre = p;
      }
      p = p.right;
    }
    return pRootOfTree;  
  }
}

4. 字符串的排列

题目描述

输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。

分析

原文连接

1、递归算法

对于无重复值的情况

固定第一个字符,递归取得首位后面的各种字符串组合;

再把第一个字符与后面每一个字符交换,并同样递归获得首位后面的字符串组合;

递归的出口,就是只剩一个字符的时候,递归的循环过程,就是从每个子串的第二个字符开始依次与第一个字符交换,然后继续处理子串。

假如有重复值呢?

由于全排列就是从第一个数字起,每个数分别与它后面的数字交换,我们先尝试加个这样的判断——如果一个数与后面的数字相同那么这两个数就不交换了。

例如abb,第一个数与后面两个数交换得bab,bba。然后abb中第二个数和第三个数相同,就不用交换了。

但是对bab,第二个数和第三个数不 同,则需要交换,得到bba。

由于这里的bba和开始第一个数与第三个数交换的结果相同了,因此这个方法不行。

换种思维,对abb,第一个数a与第二个数b交换得到bab,然后考虑第一个数与第三个数交换,此时由于第三个数等于第二个数,

所以第一个数就不再用与第三个数交换了。再考虑bab,它的第二个数与第三个数交换可以解决bba。此时全排列生成完毕!


代码

import java.util.ArrayList;
import java.util.Set;
public class Solution {
    public ArrayList Permutation(String str) {
        ArrayList list = new ArrayList();
        if(str!=null&&str.length()>0){
            PermutationHelper(str.toCharArray(),0,list);
            Collections.sort(list);
        }
        return list;
    }
    private void PermutationHelper(char[] chars,int i,ArrayList list){
        if(i == chars.length-1){
            
        }else{
            Set charSet = new HashSet();
            for(int j = i;j

你可能感兴趣的:(剑指Offer编程题(5)二叉树中和为某一值的路径)