直通BAT算法面试题总结

题1:

/**
 * 题干:对于两棵彼此独立的二叉树A和B,请编写一个高效算法,检查A中是否存在一棵子树与B树的拓扑结构完全相同。
 * 给定两棵二叉树的头结点A和B,请返回一个bool值,代表A中是否存在一棵同构于B的子树
 * 
 * 解析:其实就是将树序列化为字符串来解决就行。然后在判断一下是否包含。
 *
 */

class Solution{
        public boolean solve(TreeNode A, TreeNode B) {
            StringBuffer stringBufferA =new StringBuffer();
            StringBuffer stringBufferB =new StringBuffer();

            preOrderTraverse(A,stringBufferA);
            preOrderTraverse(B,stringBufferB);
            return stringBufferA.toString().contains(stringBufferB.toString());

        }

        //二叉树前序遍历序列化树
        public void preOrderTraverse(TreeNode node,StringBuffer stringBuffer){
            if(node == null)
                stringBuffer.append("");

            stringBuffer.append(node.val + "->");
            preOrderTraverse(node.left,stringBuffer);
            preOrderTraverse(node.right,stringBuffer);
        }
    }

    class TreeNode {
        int val = 0;
        TreeNode left = null;
        TreeNode right = null;

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

这里写图片描述
这里写图片描述
这里写图片描述

题2:

/**
 * 题干:对于两个字符串A和B,如果A和B中出现的字符种类相同且每种字符出现的次数相同,则A和B互为变形词,
 * 请设计一个高效算法,检查两给定串是否互为变形词。
 * 给定两个字符串A和B及他们的长度,请返回一个bool值,代表他们是否互为变形词。
 * 
 * 测试样例:
 * "abc",3,"bca",3
 * 返回:true
 * 
 * 解析:可以使用固定长度的数组来做词频统计即可,
 *
 */
class Solution{
        public boolean solve(String a,int n1,String b, int n2){
            if (n1!=n2) 
                return false;
            //假设这个字符串里面只有数字型和大小写字母型,那么他们的Ascall吗范围就在128以内
            /**
             * 0-9->30-39
             * A-Z->41-90
             * a-z->97-122
             */
            int[] rate1=new int[123];//频率数组A
            int[] rate2=new int[123];//频率数组B

            char[] char1 = a.toCharArray();
            char[] char2 = b.toCharArray();

            rate(char1,rate1);
            rate(char2,rate2);

            for (int i = 0; i < rate1.length; i++) {
                if(rate1[i]!=rate2[i])
                    return false;
            }


            return true;
        }


        public void rate(char[] cs,int[] rate){
            for (int i = 0; i < cs.length; i++) {
                char c=cs[i];
                rate[c]++;
            }
        }
    }

题3:

/**
 * 题干:
 * 如果对于一个字符串A,将A的前面任意一部分挪到后边去形成的字符串称为A的旋转词。
 * 比如A="12345",A的旋转词有"12345","23451","34512","45123""51234"。
 * 对于两个字符串A和B,请判断A和B是否互为旋转词。
 * 给定两个字符串A和B及他们的长度lena,lenb,请返回一个bool值,代表他们是否互为旋转词。
 * 测试样例:
 * "cdab",4,"abcd",4
 * 返回:true
 * 
 * 解析:解决的方法很简单,只需要将A串重复两次赋值给C串,再判断C中是否包含有B,如果包含(KMP算法)有则证明是
 * (当然要先考虑A、B串的长度是否一致,不一致直接返回false)
 * 在
 */
class Solution{
    public boolean solve(String a,String b){
        return (a+a).contains(b);
    }   
}

题4:

/**
 * 题干:
 * 对于一个字符串,请设计一个算法,只在字符串的单词间做逆序调整,也就是说,字符串由一些由空格分隔的部分组成,你需要将这些部分逆序。
 * 给定一个原字符串A和他的长度,请返回逆序后的字符串。
 * 测试样例:
 * "dog loves pig",13
 * 返回:"pig loves dog"
 * 
 * 解析:首先要编写一个逆序函数:他能讲一个字符串逆序,
 * 调用这个逆序函数先将全体的字符串逆序
 * 再识别每一个单词,分别对每个单词调用逆序函数,最后将所有的单词连在一起就是最后的逆序句子了。
 * 
 *
 */
class Solution{
        public void solve(String a,int n){
            char[] cs = a.toCharArray();

            cs=reverse(cs,0,n-1, n);

            int low=0,high=0;

            while (high<n) {
                char c = cs[high];
                if(c!=' '){
                    high++;
                }else {
                    cs=reverse(cs, low, high, high-low);
                    high++;
                    while(cs[high]==' '){
                        high++;
                    }

                    low=high;//重新从一个新单词开始
                }

            }

        }

        public char[] reverse(char[] cs ,int l,int h,int n){
            if(n<=1)
                return cs;

            int low=l,high=h,deffer=0;
            char tmp;
            while(low<high){
                tmp=cs[low];
                cs[low]=cs[high];
                cs[high]=tmp;
                low++; high--;
            }

            return cs;
        }
    }

题5:


/**
 * 题干:
 * 对于一个字符串,请设计一个算法,将字符串的长度为len的前缀平移到字符串的最后。
 * 给定一个字符串A和它的长度,同时给定len,请返回平移后的字符串。
 * 测试样例:
 * "ABCDE",5,3
 * 返回:"DEABC"
 * 
 * 解析:就和之前的句子逆序的思想是一致的,
 * 首先我们将他的前缀和后缀分别逆序,最后在将他整体逆序就行。
 *
 */
class Solution{
        public String  solve(String s,int n,int l){
            char[] cs= s.toCharArray();

            reverse(cs, 0, l-1, l);     //前缀逆序
            reverse(cs, l, n-1, n-l);   //后缀逆序
            reverse(cs, 0, n-1, n);     //整体逆序

            StringBuilder stringBuilder=new StringBuilder();
            for (char c : cs) {
                stringBuilder.append(c);
            }

            return stringBuilder.toString();
        }


        public void reverse(char[] cs ,int l,int h,int n){
            if(n<=1)
                return;

            int low=l,high=h,deffer=0;
            char tmp;
            while(low<high){
                tmp=cs[low];
                cs[low]=cs[high];
                cs[high]=tmp;
                low++; high--;
            }

        }
    }

题6:

/**
 * 题干:
 * 对于一个给定的字符串数组,请找到一种拼接顺序,使所有小字符串拼接成的大字符串是所有可能的拼接中字典序最小的。
 * 给定一个字符串数组strs,同时给定它的大小,请返回拼接成的串。
 * 测试样例:
 * ["abc","de"],2
 * "abcde"
 * 
 * 
 * 解析:主要就是要根据字符串的compareTo方法对字符串数组进行排序。排完以后一拼接就是最小字典序
 * 通过compareTo定义它的大小规则然后在通过Arrays.sort()直接就可以排序啦!
 *
 */
class Solution{
        public String solve(String[] strs,int n){
              if(strs==null || n==0) 
                  return null;

              Arrays.sort(strs,new Sortor());//对数组就行排序

              StringBuffer ss =new StringBuffer();

              for(int i=0;i<n;i++){  
                 ss.append(strs[i]);  
              }

              return ss.toString();  

        }
    }

    class Sortor implements Comparator<String>{

        @Override
        public int compare(String o1, String o2) {
            //此方法如果这个字符串是等参数字符串那么返回值0,==  
            //如果这个字符串是按字典顺序小于字符串参数那么返回小于0的值,<  
            //如果此字符串是按字典顺序大于字符串参数那么一个大于0的值 >  
            return (o1+o2).compareTo(o2+ o1);
        }


    }

题7:

/**
 * 题干:
 * 对于一个字符串,请设计一个算法,判断其是否为一个合法的括号串。
 * 给定一个字符串A和它的长度n,请返回一个bool值代表它是否为一个合法的括号串。
 * 测试样例:
 * "(()())",6
 * 返回:true
 * 测试样例:
 * "()a()()",7
 * 返回:false
 * 测试样例:
 * "()(()()",7
 * 返回:false
 * 
 * 解析:设置一个计数变量num,当出现左括号的时候num++,出现右括号的时候num--,
 * 在遍历过程中如果出现num<0,直接返回false,因为此时遍历过的字符串中已经多了一个右括号了
 * 遍历到最后如果num=0那么返回true,如果num>0那么证明多了左大括号。
 * 
 *
 */
class Solution{
        public boolean solve(String s,int n){
            int num=0;
            for (int i = 0; i < n; i++) {
                if (s.charAt(i)=='(') 
                    num++;
                else
                    num--;

                if(num<0){
                    return false;
                }
            }

            if (num==0)
                return true;
            else
                return false;

        }
    }

题7:

/**
 * 题干:
 *  
 * 对于一个字符串,请设计一个高效算法,找到字符串的最长无重复字符的子串长度。
 * 给定一个字符串A及它的长度n,请返回它的最长无重复字符子串长度。保证A中字符全部为小写英文字符,且长度小于等于500。
 * 测试样例:
 * "aabcb",5
 * 返回:3
 * 
 * 解析:用一个int的数组记录每一个字符上一次出现的位置,第二次出现的时候就代表重复了。
 *
 */
class Solution{
        public  int solve(String s,int n){
            int max_len = 0;
            int[] index = new int[128]; // 这里面存的是当前的字符在字符串中是第几位,而不是当前字符在字符串中的下标(加一的关系)。
            int low=0;

            // 
            for (int j = 0; j < n; j++) {
                //aaweracbdefg 
                char c = s.charAt(j);
                int a = index[c];

                low = Math.max(a, low);//如果这里出现的是重复字符,那么他的这次出现的位置   一定大于等于上次出现存储在index中的值

                max_len = Math.max(max_len, j + 1 - low );

                index[c] = j + 1;
            }

            return max_len;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值