【精选】JAVA算法题(二十三)

一、完全平方数

题目:

/**
 *给定一个正整数 num,编写一个函数,如果 num 是一个完全平方数,则返回 True,否则返回 False。
 * 说明:不要使用任何内置的库函数,如  sqrt。
 *
 * 示例 1:
 * 输入:16
 * 输出:True
 *
 * 示例 2:
 * 输入:14
 * 输出:False
 */

不使用库函数来判断一个数是不是一个完全平方数-----》判断该数开平方是不是一个整数------》从0到该数之前有没有一个数字是该数开平方的根-----》二分查找 是否存在一个数的平方等于该数字

    public boolean method1(int num) {
        if(num == 0) return true;
        int left = 1, right = num < 46340 ? num : 46340, temp = 0;
        while(left <= right){
            temp = (left + (right - left) / 2);
            if(num > temp * temp){
                left = temp + 1;
            }else if(num == temp * temp){
                return true;
            }else{
                right = temp - 1;
            }
        }
        return false;
    }

利用数学知识,找规律

1=1

4=1+3

9=1+3+5

16=1+3+5+7

25=1+3+5+7+9

发现了吗?完全平方数肯定是前n个连续奇数的和 n^2=1+3+5+7+9+…+(2n-1)

利用这样规律从1开始减,不断的减,看最后是否可以等于0;

    public boolean method2(int num) {
        int sumnum = 1; while(num>0){
            num-=sumnum;
            sumnum+=2;
        }
        return num==0;
    }

二、数组的交集 I

题目:

/**
 * 给定两个数组,编写一个函数来计算它们的交集。
 * 

* 示例 1: * 输入: nums1 = [1,2,2,1], nums2 = [2,2] * 输出: [2] *

* 示例 2: * 输入: nums1 = [4,9,5], nums2 = [9,4,9,8,4] * 输出: [9,4] *

* 说明: * 输出结果中的每个元素一定是唯一的。 * 我们可以不考虑输出结果的顺序。 */

如果这道题用python来解的话就十分简单了,因为python支持set运算,直接一行代码就出来了

return list(set(nums1) & set(nums2))

java中也实现了功能相同的方法,不过set和数组转换就不如python那般简单了

    public int[] method1(int[] nums1, int[] nums2) {
        Set integers = new HashSet<>();
        for (int a : nums1) {
            integers.add(a);
        }
        Set integers1 = new HashSet<>();
        for (int a : nums2) {
            integers1.add(a);
        }
        integers.retainAll(integers1);
        int[] ints = new int[integers.size()];
        int i = 0;
        for (int a : integers) {
            ints[i] = a;
            i++;
        }
        return ints;
    }

也可以不使用该函数,而是自己去一个个判断元素是否存在,实际上retainAll函数内部也是这么实现的

    public int[] method2(int[] nums1, int[] nums2) {
        Set set1 = new HashSet<>();
        Set set2 = new HashSet<>();
        Set set3 = new HashSet<>();
        for (int i : nums1) {
            set1.add(i);
        }
        for (int i : nums2) {
            if (set1.contains(i))
                set3.add(i);
        }
        int[] result = new int[set3.size()];
        int i = 0;
        for (Integer integer : set3) {
            result[i++] = integer;
        }
        return result;
    }

我们也可以先对其进行排序,随后再用俩指针去判断是否存在相等的元素,这样的效率更高一些,但写起来很是麻烦,需要很多判断

    public int[] method3(int[] nums1, int[] nums2) {
        Arrays.sort(nums1);
        Arrays.sort(nums2);
        int i = 0,j=0,k=0;
        while (i < nums1.length && j < nums2.length) {
            if (nums1[i] == nums2[j]) {
                nums1[k++] = nums1[i];
                i++;
                while (i < nums1.length && nums1[i] == nums1[i - 1]) {
                    i++;
                }
                j++;
                while (j < nums2.length && nums2[j] == nums2[j - 1]) {
                    j++;
                }
            } else if (nums1[i] < nums2[j]) {
                i++;
                while (i < nums1.length && nums1[i] == nums1[i - 1]) {
                    i++;
                }
            } else {
                j++;
                while (j < nums2.length && nums2[j] == nums2[j - 1]) {
                    j++;
                }
            }
        }
        int[] ret = new int[k];
        for (int l = 0; l < k; l++) {
            ret[l] = nums1[l];
        }
        return ret;
    }

借鉴一下之前用过很多次的把元素转换成数组下标的方式,一遍循环赋值,一遍循环查找并计数,一遍赋值数组,返回结果,因为是操作的数组,所以这种的效率是最高的,但如果其中出的数字少但跨度大,所需的内存就会多出好多。

    public int[] method4(int[] nums1, int[] nums2) {
        // 确定数组 nums1 的取值范围
        int max = Integer.MIN_VALUE;
        int min = Integer.MAX_VALUE;
        for (int num : nums1) {
            if (num > max) {
                max = num;
            }
            if (num < min) {
                min = num;
            }
        }
        boolean[] arr = new boolean[max - min + 1];
        for (int num : nums1) {
            arr[num - min] = true;
        }
        // 判断数组 nums2 中的数是否在数组 nums1 中存在,
        // 如果存在保存在数组 tmp 中
        int[] tmp = new int[max - min + 1];
        int idx = 0;
        for (int num : nums2) {
            if (num >= min && num <= max && arr[num - min]) {
                tmp[idx++] = num;
                arr[num- min] = false;
            }
        }
        // 返回结果
        int[] ret = new int[idx];
        for (int i = 0; i < idx; i++) {
            ret[i] = tmp[i];
        }
        return ret;
    }

三、数组的交集 II

题目:

/**
 * 给定两个数组,编写一个函数来计算它们的交集。
 *
 * 示例 1:
 * 输入: nums1 = [1,2,2,1], nums2 = [2,2]
 * 输出: [2,2]
 *
 * 示例 2:
 * 输入: nums1 = [4,9,5], nums2 = [9,4,9,8,4]
 * 输出: [4,9]
 *
 * 说明:
 *     输出结果中每个元素出现的次数,应与元素在两个数组中出现的次数一致。
 *     我们可以不考虑输出结果的顺序。
 *
 * 进阶:
 *     如果给定的数组已经排好序呢?你将如何优化你的算法?
 *     如果 nums1 的大小比 nums2 小很多,哪种方法更优?
 *     如果 nums2 的元素存储在磁盘上,磁盘内存是有限的,并且你不能一次加载所有的元素到内存中,你该怎么办?
 */

这道题就是上面那道题的进阶,多了一个数字出现次数的规则。那第一时间想到的就是Map解决,先统计每个数字出现的次数,然后比对运算。代码超简单。

    public int[] method3(int[] nums1, int[] nums2) {
        HashMap integerHashMap=new HashMap<>();
        for (int a:nums1){
            integerHashMap.put(a,integerHashMap.getOrDefault(a,0)+1);
        }
        ArrayList integers=new ArrayList<>();
        for (int a:nums2){
            if (integerHashMap.get(a)!=null&&integerHashMap.get(a)>0){
                integerHashMap.put(a,integerHashMap.get(a)-1);
                integers.add(a);
            }
        }
        int[] ints=new int[integers.size()];
        for (int i=0;i

类似的事情也可以使用集合来实现啊,集合可以再比对完后使用remove移除指定元素

    public int[] method1(int[] nums1, int[] nums2) {
        List list1 = new ArrayList<>();
        for (int num : nums1) {
            list1.add(num);
        }
        List list2 = new ArrayList<>();
        for (int num : nums2) {
            if (list1.contains(num)) {
                list2.add(num);
                // 从 list1 除去已匹配的数值
                list1.remove(Integer.valueOf(num));
            }
        }
        int[] res = new int[list2.size()];
        int i = 0;
        for (int num : list2) {
            res[i++] = num;
        }
        return res;
    }

最近学了java8(出了好久好久了。。。。),来用java8写一遍

    public int[] method2(int[] nums1, int[] nums2) {
        List list1 = Arrays.stream(nums1)
                .boxed()
                .collect(Collectors.toList());
        List list2 = Arrays.stream(nums2)
                .boxed()
                .filter(num -> {
                    if (list1.contains(num)) {
                        list1.remove(num);
                        return true;
                    }
                    return false;
                })
                .collect(Collectors.toList());
        int[] res = new int[list2.size()];
        for (int i = 0; i < list2.size(); i++) {
            res[i] = list2.get(i);
        }
        return res;
    }

还是像上一道题那样预排序一下,然后使用两个指针比对

    public int[] method4(int[] nums1, int[] nums2) {
        Arrays.sort(nums1);
        Arrays.sort(nums2);
        List list = new ArrayList<>();
        for (int i = 0, j = 0; i < nums1.length && j < nums2.length; ) {
            if (nums1[i] < nums2[j]) {
                i++;
            } else if (nums1[i] > nums2[j]) {
                j++;
            } else {
                list.add(nums1[i]);
                i++;
                j++;
            }
        }
        int[] res = new int[list.size()];
        for (int i = 0; i < list.size(); i++) {
            res[i] = list.get(i);
        }
        return res;
    }

在java中可以使用Arrays.copyof来copy数组,如果只在数组上进行操作会快上不少,和上一种方法同一种思路,最后使用Arrays.copyof来替代一次for循环和list的使用。

    public int[] method5(int[] nums1, int[] nums2) {
        Arrays.sort(nums1);
        Arrays.sort(nums2);

        int i = 0, j = 0;
        int [] ans = new int [nums2.length];
        int index = 0;
        while(i++ < nums1.length && j++ < nums2.length){
            if(nums1[i - 1] == nums2[j - 1])
                ans[index++] = nums1[i - 1];
            else if(nums1[i - 1] < nums2[j - 1])
                j--;
            else
                i--;
        }
        return Arrays.copyOf(ans, index);
    }

 

你可能感兴趣的:(Java,JAVA算法题总结,java算法题)