近日,某乎爆出大料,腾讯Android程序员私自泄露面试资料

近日,某乎上出现了一大部分腾讯还未发表出来的面试题,大多以算法为主,而且这些面试题经证实,确实是腾讯在拟还为发表的面试题目,一时间,某乎上瞬间就炸开了锅。

经查证,是腾讯某技术部的程序员私自泄露给他的一个好友的,然后他好友竟然将其上传到自己的技术博客上来博取关注,虽然事情及时止损,并没有造成严重后果,博主也及时删除了该帖,但是按照腾讯的性格,该程序员被劝退,并且被要求赔偿,具体的事情还在商议。

虽然该帖被删除了,但是有心之人已经将该面试题保存下来了,这也是我费了很大的心里才找到的,下面我也会分享给大家,虽然该面试题已经被公开了,但是知道的人也是相对来说比较少的,也有想当的借鉴意义,起码能够知道腾讯接下来面试所考核的方面。

关于算法方面

关于泄露出来的面试题因为篇幅原因没有全部上传,有需要的可以上Github自行领取哦
题目:

在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

分析:

根据题意画了个简单的图,首先我们要确定查找开始的位置,因为它是二维的数组,它的下标变化是两个方向的,根据四个边界点来分析。

a b

c d

A:向下 增 ,向右 增

B:向左 减 ,向下 增

C:向上 减 ,向右 增

D:向左 减 ,向上 减

可以看出从B 或C点开始查找刚好可以构建一个二叉查找树。

二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。

先确定二维数组的行数和列数,把 查找值 与 二叉查找树的根节点(B或者 C)开始比较,如果相等返回true,小于查找左子树,大于就查找右子树。如果遍历超过数组边界,就返回 false。

以C为根节点查找

public class Solution {
    public boolean Find(int [][] array,int target) {

        int i = array.length -1;
        int m = array[0].length -1;
        int j = 0;

        while(i>=0 && j<=m){
            if(target == array[i][j]){
                return true;
            }else if(target >array[i][j]){
                j++;
            }else{
                i--;
            }
        }

        return false;
    }
}

以B为根节点查找

public class Solution {
    public boolean Find(int [][] array,int target) {

        int i = array.length -1;
        int j = array[0].length -1;
        int n = 0;

        while(j>=0 && n<=i){
            if(target == array[n][j]){
                return true;
            }else if(target >array[n][j]){
                n++;
            }else{
                j--;
            }
        }

        return false;
    }
}

输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。

题目分析

解法一  运行时间:29m  占用内存:629k

public int  NumberOf1(int n) {
        String s=Integer.toBinaryString(n);
        char[] c=s.toCharArray();
        int j=0;
        for(int i=0;i<c.length;i++){

                if(c[i]=='1'){
                    j++;
                }

        }
        return j;
     }
}

解析:

public static String toBinaryString(int i)

以二进制(基数 2)无符号整数形式返回一个整数参数的字符串表示形式。

①先把整数转换成二进制字符串

②把字符串转换成字符数组

③遍历该数组,判断每位是否为1,为1 计数加1。

④遍历完成返回1的个数

解法二 运行时间:30ms 占用内存:629k

public class Solution {
public int  NumberOf1(int n) {
      int count =0;
      while(n!=0){
          count++;
          n = n&(n-1);
      }
     return count; 
   }
}

解析:

如果一个整数不为0,那么这个整数至少有一位是1。如果我们把这个整数减1,那么原来处在整数最右边的1就会变为0,原来在1后面的所有的0都会变成1(如果最右边的1后面还有0的话)。其余所有位将不会受到影响。

举个例子:

①二进制数  1100

② 减1后,得 1011

③1100&1011=1000

对比①和③你会发现,把一个整数减去1,再和原整数做与运算,会把该整数最右边一个1变成0.那么一个整数的二进制有多少个1,就可以进行多少次这样的操作。

定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数。

import java.util.Stack;

public class Solution {

    Stack<Integer> stack = new Stack<Integer>();
    Stack<Integer> min = new Stack<Integer>();
    public void push(int node) {
        stack.push(node);
        if(min.isEmpty()){
            min.push(node);
        }else{
          if (node <= min.peek()) {
            min.push(node);
          }
        }
    }

    public void pop() {
        if (stack.peek() == min.peek()) {
          min.pop();
        }
        stack.pop();
    }

    public int top() {
        return stack.peek();
    }

    public int min() {
        return min.peek();
    }
}

请实现一个函数,将一个字符串中的空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。

输入描述

str 是StringBuffer的对象

输出描述

返回替换后的字符串的String对象

题目分析

首先要对输入参数进行判空和越界判断(任何算法题都要注意)。

解法一 (运行时间:36ms 占用内存:688k)

public class Solution {
    public String replaceSpace(StringBuffer str) {
        if(str==null){
            return null;
        }
        StringBuffer sb = new StringBuffer();
        char [] strChar = str.toString().toCharArray();
        for(int i=0;i<strChar.length;i++){
            if(strChar[i]==' '){
                sb.append("%20");
            }else{
                sb.append(strChar[i]);
            }
        }
        return sb.toString();
    }
}

把传入的StringBuffer 对象 str 转换成字符串 再转换成字符数组,申请一个新的StringBuffer 对象 sb来存最后的结果,遍历整个字符数组,如果当前字符为空格则把 "%20"加入到sb中,否则直接追加当前字符,最后把sb转换成字符串返回。

解法二 (运行时间:34ms 占用内存:503k)

public class Solution {
    public String replaceSpace(StringBuffer str) {
        if(str == null){
            return null;
        }
        for(int i =0;i<str.length();i++){
            char c = str.charAt(i);
            if(c==' '){
                str.replace(i,i+1,"%20");
            }
        }
        return str.toString();
    }
}

public StringBuffer replace(int start, int end, String str)

使用给定 String 中的字符替换此序列的子字符串中的字符。该子字符串从指定的 start 处开始,一直到索引 end - 1 处的字符,如果不存在这种字符,则一直到序列尾部。先将子字符串中的字符移除,然后将指定的 String 插入 start。(如果需要,序列将延长以适应指定的字符串。)参数:start - 起始索引(包含)。end - 结束索引(不包含)。str - 将替换原有内容的字符串。返回:此对象。

源码(可以看出它调用的是父类的方法)

  public synchronized StringBuffer More ...replace(int start, int end, String str){
        toStringCache = null;
        super.replace(start, end, str);
        return this;
 }

父类AbstractStringBuilder

     public AbstractStringBuilder More ...replace(int start, int end, String str) {
         if (start < 0)
             throw new StringIndexOutOfBoundsException(start);
         if (start > count)
             throw new StringIndexOutOfBoundsException("start > length()");
         if (start > end)
             throw new StringIndexOutOfBoundsException("start > end");

         if (end > count)
             end = count;
         int len = str.length();
         int newCount = count + len - (end - start);
         ensureCapacityInternal(newCount);

         System.arraycopy(value, end, value, start + len, count - end);
         str.getChars(value, start);
         count = newCount;
         return this;
     }

可以看出StringBuffer类 提供了 插入的函数,值得注意的是 StringBuilder 也是继承于AbstractStringBuilder这个抽象类的。所以它也有这个方法,但是String并没有。

解法三(不推荐,运行时间:38ms 占用内存:654k)

public class Solution {
    public String replaceSpace(StringBuffer str) {
        return str.toString().replaceAll("\\s", "%20");
    }
}

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

输入描述

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

输出描述

顺序输出字符串的所有排列

题目分析

这是一个字符串全排列的问题,把全部序列存在TreeSet中默认可得到字典顺序。

TreeSet     基于TreeMap实现的SortedSet,可以对Set集合中的元素进行排序,排序后按升序排列元素(缺省是按照自然排序),非线程安全。

思路:

固定一个字符串之后,之后再将问题变小,只需求出后面子串的排列个数就可以得出结果,然后依次将后面的字符串与前面的交换,再递归子串的排列结果,最后当所有字符都固定结束递归。

下面这张图很清楚的给出了递归的过程:

解法 运行时间:131ms 占用内存:1477k

import java.util.*;
public class Solution {
    //用于最后返回结果
    ArrayList<String> list  = new ArrayList<>();
    //遍历的时候来存储序列实现排序
    TreeSet<String> set = new TreeSet<>();

    public ArrayList<String> Permutation(String str) {      
       if(str==null || str.length()==0) return list;

       Permutation(str.toCharArray(),0);
       //容器转换,TreeSet中的元素已经是按照字母顺序排序,所以这里做了排序
       list.addAll(set);
       return list;
    }
    public void Permutation(char[] s,int index){
        if(s==null ||s.length==0 || index<0 || index>s.length-1)  return ;
        if(index==s.length-1){//递归固定到最后一个位置,把该串加入集合
            // set不能添加重复元素,所以这里的add()解决了有重复字符的问题
            set.add(new String(s));
        }else{//固定前index+1个字符,递归后面所有可能的子串
           for(int i = index;i<s.length;i++){
               swap(s,index,i);//交换一次形成一个子串
               Permutation(s,index+1);
               swap(s,i,index);//复原使下次循环产生下一个子串
           }
        }
    }
    public void swap(char[] s,int i,int j){
        char temp = s[i];
        s[i] = s[j];
        s[j] = temp;
    }
}

其他的面试题我也有收集,最新的技术,类似于Flutter,KT,Jetpack+mvvm.....有需要的小伙伴可以上Github自行领取哦

猜你喜欢

转载自blog.csdn.net/Androidbye/article/details/115210810
今日推荐