java面试算法题目

下面所有代码采用 java 编写

1.针对给定的⼀维数组,⽐如[1, 1, 34, 9, 45, 8, 3, 21, 6, 1, 8, 3, 7, 6, 22, 88, 34, 21];请使⽤⼀次 for循环,找出所有的重复数字以及重复数字的次数;

思路
对于给定的数组,我们对每一个元素和后面的每一个元素都进行比较,如果相等计数器加一,这样就能得出重复的元素和个数了。
但是这样有个问题,后面重复的元素再跟后面的元素比较,这样就会重复打印,而且第二次打印就会比上一次打印的少计算一个,我们需要把这种情况剔除掉。

步骤
1.遍历整个数组,依次的拿到每一个的数值
2.在循环内部,对于拿到的元素需要和之前的进行比较,如果相同就得跳过这次比较,因为这个已经打印过了。
3.对于没比较的,可以循环的和后面的每一次进行比较
4.对于计数器大于1的,说明重复了

代码实现

    @Test
    public void getRepeatNum(){
        List<Integer> list = Arrays.asList(1, 1, 34, 9, 45, 8, 3, 21, 6, 1, 8, 3, 7, 6, 22, 88, 34, 21);
        //1.遍历整个数组,依次的拿到每一个的数值
        for(int i = 0;i < list.size();i++){
            //2.先判断这个元素之前是不是已经计算过了
            boolean flag = false;
            for(int k=0;k<i;k++){
                if(list.get(k) == list.get(i)){
                    flag = true;
                    //只要发现是计算过,直接跳出循环,节省资源
                    break;
                }
            }
            //计算过了就直接下一步
            if(flag){
                continue;
            }

            //3.之前没有计算过 重新计算
            int count = 1;   //计数器初始值是1,因为每个元素至少出现1次
            for(int j= i+1;j < list.size();j++){
                if(list.get(i) == list.get(j)){
                    count++;
                }
            }
            //4.计算大于1,就打印出来
            if(count>1){
                System.out.println("重复元素" + list.get(i) + "出现了" + count + "次");
            }
        }

    }

这样整个方法就出来了,思路很清晰,也去除了重复比较的问题,但是题目要求一个for循环。

思路
将第二步和第三步的内部for循环改写成递归调用

代码实现

    @Test
    public void getRepeatNum2(){
        List<Integer> list = Arrays.asList(1, 1, 34, 9, 45, 8, 3, 21, 6, 1, 8, 3, 7, 6, 22, 88, 34, 21);
        //1.遍历整个数组,依次的拿到每一个的数值
        for(int i = 0;i < list.size() - 1;i++){
            if(i != 0){
                //2.先判断这个元素之前是不是已经计算过了
                boolean bool = compareBefore(list, i, 0);
                //计算过了就直接下一步
                if(bool){
                    continue;
                }
            }
            //3.之前没有计算过 重新计算
            int count = 1;   //计数器初始值是1,因为每个元素至少出现1次
            count = repeaSearch(list, i, i + 1, count);
            //4.计算大于1,就打印出来
            if(count>1){
                System.out.println("重复元素" + list.get(i) + "出现了" + count + "次");
            }
        }

    }
    public static boolean compareBefore(List<Integer> list,int index,int first){
        if(list.get(index) == list.get(first)){
            return true;
        }else if(first < index -1 ){
            return compareBefore(list,index,first+1);
        }else {
            return false;
        }
    }

    public static int repeaSearch(List<Integer> list,int index, int end,int count){
        if(list.get(index) == list.get(end)){
            count++;
        }
        if(end < list.size() -1 ){
            return repeaSearch(list,index,end+1,count);
        }else {
            return count;
        }
    }

2.给定指定数组,⽐如【1, 2, 3, 4, 5, 6, 7, 8, 9, 10】,在数组中查找⼀个元素的下标,要求:使 ⽤递归⽅式、⼆分查找算法、不得使⽤所使⽤语⾔已有的函数;

这里对于递归调用和二分法查找,我们有个前提是这个数组是不重复的,而且是已经排序完成的数组
这样我们对于已经排序完成的数组,进行查找才能精确的查找到下标的位置

思路
1.先进性排序 排序后是我们需要查找下标的数组 打印出来
2.递归的方法代替for循环,二分法查找

代码实现

  @Test
    public void getRepeatSubscript(){
        List<Integer> list = Arrays.asList(1,5,7,8,19,3,58,65,27,2);  //查找下标,我们限定数组不重复
        //1.先进行排序 冒泡
        for(int i = 0;i < list.size();i++){
            for(int j= i+1;j < list.size();j++){
                if(list.get(i) > list.get(j)){
                    Collections.swap(list,i,j);  //交换元素位置
                }
            }
        }
        System.out.println("查找的目标数组:" + list);  //这个数组才是我们最终查找的下标
        //2.进性二分法查找 递归
        int i = binarySearch(list, 19, 0, list.size());//查找19
        System.out.println("下标位置为" + i);

    }

    public static int binarySearch(List<Integer> list,int num,int min,int max){
        if(max < min){
            return -1;  //查不到返回-1
        }
        int mid = (max + min)/2;
        if(list.get(mid) == num){
            return mid;
        }else if(list.get(mid) > num){
            return binarySearch(list,num,min,mid-1);
        }else {
            return binarySearch(list,num,mid+1,max);
        }
    }

3.编程题:有⼀堆糖果,其数量为n,现将糖果分成不同数量的堆数(每堆数量均为整数,最少为 1),请算出糖果堆对应数量的最⼤乘积是多少,并给出对应的分配⽅案; 举例:糖果数量为8,可以得到的乘积最⼤为18,对应的分配⽅案为【2,3,3】;

这里我们思考了一下如何让乘积最大
1.1要首先排除掉
2.分解的堆数尽量多
3.做到每个数都想接近

我们把这个数 2 * 3 的方式分解 得到的* 最大 尽量多的3
但是不能有1 有1 就得把1 加在2 上

第一种情况,刚好是三的倍数,直接相乘
第二种情况,余数是1 这种坚决要不得 少一个3 变成2* 2
第三种情况 余数为2 那就直接*2就行

代码实现

  @Test
    public void greedyAlgorithm(){
        int num = 15;
        //1 2 3 4 不在算法计算之内
        switch (num){
            case 1:
                System.out.println("最大的乘积1");
            case 2:
                System.out.println("最大的乘积1");
            case 3:
                System.out.println("最大的乘积2");
            case 4:
                System.out.println("最大的乘积4");
        }

        //我们从5开始考虑,尽量多的3
        int number = num/3; //算出几个3
        int remainder = num - 3*number;
        int product = 1;
        if(remainder == 0){
            //第一种情况,刚好是三的倍数,直接相乘
           for (int i = 0;i<number;i++ ){
               product = product *3;
           }
        }else if(remainder == 1){
            //第二种情况,余数是1 这种坚决要不得 少一个3 变成2* 2
            for (int i = 0;i<number-1;i++ ){
                product = product *3;
            }
            product = product *2*2;
        }else {
            //第三种情况 余数为2 那就直接*2就行
            for (int i = 0;i<number;i++ ){
                product = product *3;
            }
            product = product *2;
        }

        System.out.println(product);
    }
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值