NewCoder Algorithm Part2(数组全排列、字符串的全排列、第一次只出现一次的字符、树的子结构、二叉树的对称性、和为S的两个数)

数组的全排列
class Solution {
public:
    vector<vector<int>> res;
    /*
     * @param nums: A list of integers.
     * @return: A list of permutations.
     */
    vector<vector<int>> permute(vector<int> &nums) {
        // write your code here
        vector<int> value;
        proccess(nums,0);
        return res;
    }
    void proccess(vector<int> &nums, int index){
        if(index == nums.size()){
            res.push_back(nums);
            return;
        }
        for (int j = index; j < nums.size() ; j++) {
            swap(nums[index], nums[j]);
            proccess(nums, index+1);//point1
            swap(nums[index], nums[j]);
        }
    }
};
题目描述

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

输入描述:

输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。

  全排列在非常多程序都有应用,是一个非经常见的算法,常规的算法是一种递归的算法,这样的算法的得到基于下面的分析思路。  给定一个具有n个元素的集合(n>=1),要求输出这个集合中元素的全部可能的排列。

        一、递归实现

        比如,假设集合是{a,b,c},那么这个集合中元素的全部排列是{(a,b,c),(a,c,b),(b,a,c),(b,c,a),(c,a,b),(c,b,a)},显然,给定n个元素共同拥有n!种不同的排列,假设给定集合是{a,b,c,d},能够用以下给出的简单算法产生其全部排列,即集合(a,b,c,d)的全部排列有以下的排列组成:

     (1)以a开头后面跟着(b,c,d)的排列

    (2)以b开头后面跟着(a,c,d)的排列

    (3)以c开头后面跟着(a,b,d)的排列

    (4)以d开头后面跟着(a,b,c)的排列,这显然是一种递归的思路,于是我们得到了下面的实现:

class Solution {
public:
    vector<string> Permutation(string str) 
    {
        vector<string> array ;
        if(!str.size()) return array;
        Permutation(array,str,0);
        return array;
    }
   void  Permutation(vector<string> &array,string str,int begin){
       if(begin==str.size())
           array.push_back(str);
       for(int i =begin; i< str.size();i++){
           swap(str[i],str[begin]);
           Permutation(array,str,begin+1);
           swap(str[i],str[begin]);
       }  
   }
};

 有时候递归的效率使得我们不得不考虑除此之外的其它实现,非常多把递归算法转换到非递归形式的算法是比較难的,这个时候我们不要忘记了标准模板库已经实现的那些算法,这让我们非常轻松。STL有一个函数next_permutation(),它的作用是假设对于一个序列,存在依照字典排序后这个排列的下一个排列,那么就返回true且产生这个排列,否则返回false。注意,为了产生全排列,这个序列要是有序的,也就是说要调用一次sort。实现非常easy,我们看一下代码

class Solution {
public:
    vector<string> Permutation(string str) {
        vector<string> array;
        if(str.size() == 0) return array;
           do{
            array.push_back(str);
            }
           while ( next_permutation(str.begin(),str.end()) );       
        return array;
    }
第一次只出现一次的字符

 

class Solution {
public:
    /**
     * @param str: str: the given string
     * @return: char: the first unique character in a given string
     */
    unordered_map<char,int> help;
    char firstUniqChar(string &str) {
        // Write your code here
        for (int i = 0; i < str.size(); i++) {
            help[str[i]] = help[str[i]] + 1;
        }
         for (int i = 0; i < str.size(); i++) {
           if(help[str[i]] == 1) return str[i];
        }
        return ' ';
    }
};
245. 子树
有两个不同大小的二叉树: T1 有上百万的节点; T2 有好几百的节点。请设计一种算法,判定 T2 是否为 T1的子树。

样例
样例 1:

输入:{1,2,3,#,#,4},{3,4}
输出:true
解释:
下面的例子中 T2 是 T1 的子树:

           1                3
          / \              / 
    T1 = 2   3      T2 =  4
            /
           4
样例 2:

输入:{1,2,3,#,#,4},{3,#,4}
输出:false
解释:
下面的例子中 T2 不是 T1 的子树:

           1               3
          / \               \
    T1 = 2   3       T2 =    4
            /
           4
注意事项
若 T1 中存在从节点 n 开始的子树与 T2 相同,我们称 T2 是 T1 的子树。也就是说,如果在 T1 节点 n 
处将树砍断,砍断的部分将与 T2 完全相同。
/**
 * Definition of TreeNode:
 * class TreeNode {
 * public:
 *     int val;
 *     TreeNode *left, *right;
 *     TreeNode(int val) {
 *         this->val = val;
 *         this->left = this->right = NULL;
 *     }
 * }
 */

class Solution {
public:
    /**
     * @param T1: The roots of binary tree T1.
     * @param T2: The roots of binary tree T2.
     * @return: True if T2 is a subtree of T1, or false.
     */
    bool isSubtree(TreeNode * T1, TreeNode * T2) {
        // write your code here
        if(!T2) return true;
        if(!T1) return false;
        return proccess(T1,T2)||isSubtree(T1->left,T2)||isSubtree(T1->right,T2);
    }
    bool proccess(TreeNode *t1, TreeNode*t2){
        if(!t1 && !t2) return true;
        if((t1 && !t2) || (!t1 && t2)) return false;
        if(t1->val == t2->val)
        return proccess(t1->left, t2->left) && proccess(t1->right,t2->right);
        return false;
    }
};
二叉树的堆成性

 

/**
 * Definition of TreeNode:
 * class TreeNode {
 * public:
 *     int val;
 *     TreeNode *left, *right;
 *     TreeNode(int val) {
 *         this->val = val;
 *         this->left = this->right = NULL;
 *     }
 * }
 */

class Solution {
public:
    /**
     * @param root: root of the given tree
     * @return: whether it is a mirror of itself 
     */
    bool isSymmetric(TreeNode * root) {
        // Write your code here
        if(!root)  return true;
        return proccess(root->left,root->right);
       
    }
    bool proccess(TreeNode *rootLeft, TreeNode *rootRight){
        if(!rootLeft && !rootRight) return true;
        if(rootLeft && rootRight && (rootLeft->val == rootRight->val))
            return proccess(rootLeft->left,rootRight->right) && proccess(rootLeft->right,rootRight->left);
        return false;
    }
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值