算法笔试(汇总)

1.括号的匹配,要求输出一个字符串,里面包含(){}[]<>,当字符串中括号是成对出现的时候,返回true,否则返回false
例如:{(<>{})}返回的是true,而{(})([])返回的是false
思路:利用栈的后进先出的思想

public static boolean isMatch(String input){
   Stack<Character> stack=new Stack<Character>();
   char temp;
   int len=input.length();
   //循环input
   for(int i=0;i<len;i++){
      temp=input.charAt(i);
      if(temp=='(') stack.push(')');
      if(temp=='{') stack.push('}');
      if(temp=='[') stack.push(']');
      if(temp=='<') stack.push('>');

      if(temp==')'||temp=='}'||temp==']'||temp=='>'){
         char tempok=stack.pop();
         if(temp!=tempok) return false; 
      }
   }
   if(stack.isEmpty()==true) return true;
   else return false;
}

注意:上面括号的匹配代码是有问题的,更新于20170727。因为当字符串是右括号开始的时候会出现java.util.EmptyStackException,很显然没有考虑这种情况的发生,修改下判断方式,代码如下:

  public boolean isValid(String s) {
        Stack<Character> stack=new Stack<Character>();
        for(int i=0;i<s.length();i++){
            char ch=s.charAt(i);
            if(ch=='(') stack.push(')');
            else if(ch=='{') stack.push('}');
            else if(ch=='[') stack.push(']');
            else if(stack.isEmpty() || stack.pop()!=ch)
                return false;

        }

        if(stack.isEmpty()){
            return true;
        }else{
            return false;
        }
    }

2.输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。
解题思路:利用Collections 的sort方法重写Comparator使得list中的数按照要求排好序,然后拼接list中的元素即可。

public String PrintMinNumber(int[] numbers){
        int n=numbers.length;
        ArrayList<Integer> list=new ArrayList<Integer>();
        for(int i=0;i<n;i++){
            list.add(numbers[i]);
        }

        Collections.sort(list, new Comparator<Integer>() {
           @Override
        public int compare(Integer o1, Integer o2) {
            String s1=o1+""+o2;
            String s2=o2+""+o1;
            return s1.compareTo(s2);
        }
        });

        String result="";
        for(int i:list){
            result +=i;
        }
        return result;
    }

3.求出1~n的整数中1出现的次数.
解题思路:将整数转换成String类型,然后转换为char数组,计算char中1的个数即可,代码如下:

public static int numOfOne(int n){

        int nums=0;
        if(n==0) return 0;
        while(n>0){

            String str=String.valueOf(n);
            char[] cha=str.toCharArray();
            for (int j=0;j<cha.length;j++){
                if(cha[j]=='1') nums++;
            }
            n--;
        }

        return  nums;
    }

4.输入一个链表,输出该链表中倒数第k个结点
解题思路:定义两个指针,p1和p2,p1先走k-1,然后p2开始走,当p1走到结尾为空时,p2就是要找的位置

/*链表
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
    public ListNode FindKthToTail(ListNode head,int k) {
    //判断是否为null链表或者k不合法
        if(head==null||k<=0) return null;
        ListNode p1=head;
        ListNode p2=head;
        ListNode p3=head;
        int count=0;
        while (p3 != null) {
            count++;
            p3 = p3.next;
        }
        //当k大于当前链表的长度,也是null
        if(k>count) return null;
        //p1先走k-1步
        for(int i=1;i<k;i++){
            if(p1!=null)
             p1=p1.next;

        }
        然后p1,p2同时移动,直到p1为空
        while(p1.next!=null){
            p1=p1.next;
            p2=p2.next;
        }
        return p2;
    }
}

5.输入一个字符串,包括数字字母符号,可以为空。将该字符串转换为一个整数。要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0
解题思路:

public int StrToInt(String str) {
        if(str.length()==0||str.equals("")) return 0;
        int result=0;
        int symbol=0;
        char[] chas=str.toCharArray();
        if(chas[0]=='-'){
            symbol=1;
        }
        for (int i=symbol;i<chas.length;i++){
            if (chas[i]=='+') continue;
            if (chas[i]<48||chas[i]>57) return 0;

            result =result*10+(chas[i]-48);
        }
        if (symbol==1) result=result*(-1);
        return result;
    }

6.在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是重复的数字2或者3
解题思路:将数组拼接成字符串,然后使用replaceAll关键字,如果替代后字符串的长度小于原长度-1,说明是重复数字放到duplication中,暂停循环。

    // Parameters:
    //    numbers:     an array of integers
    //    length:      the length of array numbers
    //    duplication: (Output) the duplicated number in the array number,length of duplication array is 1,so using duplication[0] = ? in implementation;
    //                  Here duplication like pointor in C/C++, duplication[0] equal *duplication in C/C++
    //    这里要特别注意~返回任意重复的一个,赋值duplication[0]
    // Return value:       true if the input is valid, and there are some duplications in the array number
    //                     otherwise false
    public boolean duplicate(int numbers[],int length,int [] duplication) {
        if(numbers==null||numbers.length==0) return false;
        String str="";

        for(int i=0;i<length;i++){
            str +=numbers[i];
        }

        for(int i=0;i<length;i++){
            String cha=numbers[i]+"";
            if(str.replaceAll(cha,"").length()<str.length()-1) {
                duplication[0] = numbers[i];
                break;
            }
        }
        //注意:这里应该判断数组的第一个元素是否大于0
        if (duplication[0]>=0){
            return true;
        }
        return false;
    }

7.寻找假币问题
解决问题:分治算法,然后递归解决

public int falsecoin(int coins[],int low,int high){//low high是索引
         int i,sum1,sum2;
         int re=0;
         sum1=sum2=0;
         if(low+1==high){//这里是边界条件,写递归的时候一定注意边界条件。
             if(coins[low]<coins[high]){
                 re=low+1;
                 return re;
             }else{
                 re=high+1;
                 return re;
             }

         }
         if((high-low+1)%2==0){//n是偶数
             for(i=low;i<=low+(high-low)/2;i++){
                 sum1=sum1 + coins[i];
             }//前半段的和
             for(i=low+(high-low)/2+1;i<=high;i++){
                 sum2=sum2 + coins[i];
             }//后半段的和
             if(sum1>sum2){//如果前半段和大于后半段和则递归继续求解
                 re=falsecoin(coins,low+(high-low)/2+1,high);
                 return re;
             }else{
                 re=falsecoin(coins,low,low+(high-low)/2);
                 return re;
             }
         }else{//n是奇数
             for(i=low;i<=low+(high-low)/2-1;i++){
                 sum1=sum1+coins[i];
             }
             for(i=low+(high-low)/2+1;i<=high;i++){
                 sum2=sum2+coins[i];
             }
             if(sum1>sum2){
                 re=falsecoin(coins,low+(high-low)/2+1,high);
                 return re;
             }else if(sum1<sum2){
                 re=falsecoin(coins,low,low+(high-low)/2);
                 return re;
             }else{
                 re=low+(high-low)/2+1;
                 return re;
             }
         }

     }

8.反转单词顺序
问题描述:例如,“student. a am I”正确的句子应该是“I am a student.”
解题思路:先将整个字符串进行反转,通过reverse()方法,然后分割反转后字符串再进行单个单词反转。

public String ReverseSentence(String str){
  if(str==null) return null;
  if(str.trim().equals("")) return str;
  String result="";
  StringBuffer sb=new StringBuffer(str);
  String sbok=sb.reverse().toString();
  String[] strs=sbok.split(" ");
  for(int i=0;i<strs.length;i++){
    StringBuffer stra=new StringBuffer(strs[i]);
    stra.reverse();
    result=result+stra+" ";
  }
  return result.trim();
}

9.扑克牌顺子
问题描述:LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54张^_^)…他随机从中抽出了5张牌,想测测自己的手气,看看能不能抽到顺子,如果抽到的话,他决定去买体育彩票,嘿嘿!!“红心A,黑桃3,小王,大王,方片5”,“Oh My God!”不是顺子…..LL不高兴了,他想了想,决定大\小 王可以看成任何数字,并且A看作1,J为11,Q为12,K为13。上面的5张牌就可以变成“1,2,3,4,5”(大小王分别看作2和4),“So Lucky!”。LL决定去买体育彩票啦。 现在,要求你使用这幅牌模拟上面的过程,然后告诉我们LL的运气如何。为了方便起见,你可以认为大小王是0。
解题思路:先按照数组中的数从小到大排列,然后统计0的个数,从非0开始循环搜索,当当前的数加上1再加上0的个数大于当前后一个数(表明中间缺的可以用0来补全),继续搜索,直到数组最后一位并且0的个数是大于等于0的。

        public static boolean isContinuous(int [] numbers) {

            if(numbers.length==0) return false;
            Arrays.sort(numbers);//先排序从小到大
            int zero=0;
            int i=0;
            for(;i<numbers.length && numbers[i]==0;i++){
                 zero++;//统计0的个数
            }
            //从非0索引开始搜索
            for(;i<numbers.length-1 && zero>=0;i++){
                if(numbers[i]==numbers[i+1]) return false;
                //0的个数可以继续匹配
                    zero =zero-(numbers[i+1]-numbers[i]-1);
                    //代表多少个0被用
                }else{
                    return false;
                }
            }

            return true;


         }

10.地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。 例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子?
解题思路:递归回溯
1.从(0,0)开始走,每成功走一步标记当前位置为true,然后从当前位置往四个方向探索,
返回1 + 4 个方向的探索值之和。
2.探索时,判断当前节点是否可达的标准为:
1)当前节点在矩阵内;
2)当前节点未被访问过;
3)当前节点满足limit限制。

 public int movingCount(int threshold,int rows,int cols){
          int flag[][]=new int[rows][cols];//记录是否已经走过
          return helper(0,0,rows,cols,flag,threshold);

      }
      private int helper(int i,int j,int rows,int cols,int[][] flag,int threshold){
          if(i<0||i>=rows||j<0||j>=cols) return 0;
          if(numSum(i)+numSum(j)>threshold||flag[i][j]==1) return 0;
          flag[i][j]=1;

          return helper(i-1,j,rows,cols,flag,threshold)
                  +helper(i+1,j,rows,cols,flag,threshold)
                  +helper(i,j-1,rows,cols,flag,threshold)
                  +helper(i,j+1,rows,cols,flag,threshold)
                  +1;
      }
      private int numSum(int i){
          int sum=0;
          while(i!=0){
              sum +=i%10;
              i=i/10;
          }
          return sum;
      }

11.输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字
例如,如果输入如下矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.

    public ArrayList<Integer> printMatrix(int[][] matrix){
        ArrayList<Integer> result=new ArrayList<Integer>();
        if(matrix==null||matrix.length==0) return result;

        printMatrixClockWisely(matrix, 0, 0, matrix.length-1, matrix[0].length-1, result);

        return result;
    }
    public void printMatrixClockWisely(int[][] matrix,int startRow,int startCol,int endRow,int endCol,ArrayList<Integer> result){
        if(startRow<endRow && startCol<endCol){
            for(int j=startCol;j<=endCol;j++) result.add(matrix[startRow][j]);
            for(int i=startRow+1;i<=endRow-1;i++) result.add(matrix[i][endCol]);
            for(int j=endCol;j>=startCol;j--) result.add(matrix[endRow][j]);
            for(int i=endRow-1;i>=startRow+1;i--) result.add(matrix[i][startCol]);
            printMatrixClockWisely(matrix, startRow+1, startCol+1, endRow-1, endCol-1, result);
        }else if(startRow==endRow && startCol<endCol){
            for(int j=startCol;j<=endCol;j++) result.add(matrix[startRow][j]);
        }else if(startRow<endRow && startCol==endCol){
            for(int i=startRow;i<=endRow;i++) result.add(matrix[i][startCol]);
        }else if(startRow==endRow && startCol==endCol){
            result.add(matrix[startRow][startCol]);
        }else {
            return;
        }

    }

12.给定一个非负整型数组,每一位代表当前位置能够跳动的最长步数,判断是够能够抵达最后一位。

public boolean canJump(int[] nums){
  if(nums==null||nums.length==0) return false;
  int n=nums.length;
  if(n==1) return true;

  int max=0;
  int i=0;
  while(i <=max && i<n){
    max=Math.max(max,nums[i]+i);
    if(max >=n-1) return true;
    i++;
  }
  return max >=n-1;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值