牛客网必刷top101之哈希BM50两数之和,BM51数组中出现次数超过一半的数字,BM52数组中只出现一次的两个数字,BM53缺失的第一个正整数, BM54三数之和

BM50两数之和

牛客链接

题目描述:给出一个整型数组 numbers 和一个目标值 target,请在数组中找出两个加起来等于目标值的数的下标,返回的下标按升序排列。

解题思路:

一般的暴力搜索思路在这里我们不做赘述,首先我们看到该题的返回值一定是一个长度为2

的int型数组,用来保存符合题意的元素的下标(注意:题目要求下标是从1开始的),所以我们创建一个数组,接下来我们创建一个hashmap用来映射数组中的元素与下标之间的关系,遍历题中给出的数组,如果target减去当前的元素可以在hashmap中找到那么这两个元素的下标一定是题目要求返回的结果,如果不是的话我们把当前的元素放入map即可,以防后面使用。

代码描述:

 public int[] twoSum (int[] numbers, int target) {
        int[] array = new int[2];
       HashMap<Integer,Integer> map = new HashMap<>();
       for (int i = 0; i < numbers.length; i++) {
           int num = target - numbers[i];
           if(map.containsKey(num)){
               array[0] = map.get(num) + 1;
               array[1] = i + 1;
               break;
           }else{
               map.put(numbers[i],i);
           }
       }
        return array;
   }

BM51 数组中出现次数超过一半的数字

牛客链接

题目描述:

给一个长度为 n 的数组,数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。

例如输入一个长度为9的数组[1,2,3,2,2,2,5,4,2]。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。

思路分析:我们创建一个hashmap来映射数组中的某元素与该元素在数组中出现的次数,然后遍历整个数组,如果map中没有该元素则把该元素放进去,并使它的value值为一,如果map中有该元素我们先要得到该元素之前出现的次数,并且让该key对应的value值加一,最后判断该key值所对应的value是否已经大于数组长度的一半。

代码描述:

 public int MoreThanHalfNum_Solution(int [] array) {
       int num = 0;
       HashMap<Integer,Integer> map = new HashMap<>();
       for (int i = 0; i < array.length; i++) {
           if(map.containsKey(array[i])){
               int value = map.get(array[i]);
               map.put(array[i],value + 1);
           }else{
               map.put(array[i],1);
           }
           if(map.get(array[i]) > array.length / 2){
               num = array[i];
               break;
           }

       }
        return num;
   }

BM52 数组中只出现一次的两个数字

牛客链接

题目描述:一个整型数组里除了两个数字只出现一次,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。

思路分析:

我们创建一个hashmap映射该元素与其在数组中出现的次数(题目中描述不是为1,就是为2)所以在往map中放元素的时候只需要判断map中有无该元素如果有的话只需要把其value值覆盖为2即可,如果没有的话设置其value值为1。最后遍历map如果某元素的value值为1的话,把它保存到要返回的数组中,由于题目要求把小的元素放在前面,所以我们调用Arrays的sort方法对目标数组进行排序。

代码描述:

 public int[] FindNumsAppearOnce(int[] array) {
        int[] result = new int[2];
        HashMap<Integer,Integer> map = new HashMap<>();
        for (int i = 0; i < array.length; i++) {
            if(! map.containsKey(array[i])){
                map.put(array[i],1);
            }else{
                map.put(array[i],2);
            }
        }
        int index = 0;
        for (Map.Entry<Integer,Integer> entry:map.entrySet()) {
            if(entry.getValue() == 1){
               result[index] = entry.getKey();
                index ++;
            }
        }
        Arrays.sort(result);
        return result;
    }

BM53 缺失的第一个正整数

牛客链接

题目描述:

给定一个无重复元素的整数数组nums,请你找出其中没有出现的最小的正整数

思路分析:

众所周知,最小的正整数为一,我们首先创建一个变量num为1,然后创建一个hashset容器,遍历整个数组,把数组中的元素放入set中,如果num在set中可以找到那么就让num一直进行加一操作,直到set中不包含num为止,遍历完整个数组返回num值即可。

代码描述:

public int minNumberDisappeared1 (int[] nums) {
        int num = 1;
        HashSet<Integer> set = new HashSet<>();
        for (int i = 0; i < nums.length; i++) {
            set.add(nums[i]);
            while(set.contains(num)){
                num ++;
            }
        }
        return num;
    }

BM54 三数之和

牛客链接

题目描述:给出一个有n个元素的数组S,S中是否有元素a,b,c满足a+b+c=0?找出数组S中所有满足条件的三元组

思路分析:

首先我们对数组进行从小到大的排序。

我们进行循环选择第一个数num[i],然后创建两个指针leftright,指针left指向下一个数,指针j指向最后一个数。

如果num[i] + num[left] +num[right]<0那么就让left指针往右走;

如果num[i] + num[left] +num[right]>0那么就让right指针往左走;

如果num[i] + num[left] +num[right]==0那么就应该保存这三个数;

以上就是我们的 大致思路,但题目中还要求了这个三元组不能重复,那么就要考虑去重,我们发现在num[i] + num[left] +num[right]==0时为了不漏解我们必须要让left和right指针相遇,但是这样一来我们就可能得到同样的num[left]和num[right],由于我们事先对num数组进行了排序所以即使有重复的值那么它必定是相连的,此时只要让指针继续走就行,不必判断这组;同理如果遇到相同的num[i]也让i继续++即可,这样便可以做到去重。

代码描述:

 public ArrayList<ArrayList<Integer>> threeSum(int[] num) {
        ArrayList<ArrayList<Integer>> result = new ArrayList<>();
        if(num.length < 3){
            return result;
        }
        Arrays.sort(num);
        for (int i = 0; i < num.length - 2;) {
            int left = i + 1;
            int right = num.length -1;
            if(num[i] > 0){
                    return result;
                }
            while (left < num.length - 1 && right > 0 &&left < right ){
                int number = num[i] + num[left] + num[right];
                if(number == 0){
                    ArrayList<Integer> arrayList = new ArrayList<>();
                    arrayList.add(num[i]);
                    arrayList.add(num[left]);
                    arrayList.add(num[right]);
                    result.add(arrayList);
                    if(num[left + 1] == num[left]){
                        while(left < num.length - 2 &&num[left + 1] == num[left]){
                            left++;
                        }
                    }
                        left++;
                   if(num[right - 1] == num[right]){
                       while(right > 0 && num[right - 1] == num[right]){
                           right--;
                       }
                   }
                       right--;

                }else if(number > 0){
                    right--;
                }else if(number < 0){
                    left ++;
                }
                if(!(left < right)){
                    break;
                }
            }
            if(num[i + 1] == num[i]) {
                while(i < num.length - 2 && num[i + 1] == num[i]){
                    i++;
                }
            }
                i++;

        }
        return result;
    }

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值