100天算法入门 - 每日三题 - Day14两个数组的交集有效的完全平方数字符串中的第一个唯一字符

Posted 哪 吒

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了100天算法入门 - 每日三题 - Day14两个数组的交集有效的完全平方数字符串中的第一个唯一字符相关的知识,希望对你有一定的参考价值。

位于半山腰的城堡酒店坐拥港口美景


算法是进阶架构师的基础,基础不牢,地动山摇,2021-8-14起开始刷题,目标100天,300道LeetCode算法题,分享是学习的最好方式,加油,嗨起来。

1、LeetCode 350.两个数组的交集

题目

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

小编菜解

public static int[] intersect(int[] nums1, int[] nums2) {
    List<Integer> list1 = new ArrayList<>();
    List<Integer> list2 = new ArrayList<>();
    for (int i = 0; i < nums1.length; i++) {
        list1.add(nums1[i]);
    }

    for (int i = 0; i < nums2.length; i++) {
        list2.add(nums2[i]);
    }
    return getIntersection(list1,list2);
}

public static int[] getIntersection(List<Integer> list1, List<Integer> list2) {
    if (list1.size()>list2.size()){
        return getIntersection(list2,list1);
    }
    List<Integer> list = new ArrayList<>();
    for (Integer x : list1){
        if (list2.contains(x)){
            list.add(x);
            list2.remove(x);
        }
    }
    int[] ret = new int[list.size()];
    for (int i = 0; i < list.size(); i++) {
        ret[i] = list.get(i);
    }
    return ret;
}

思路及算法

为了降低空间复杂度,首先遍历较短的数组并在哈希表中记录每个数字以及对应出现的次数,然后遍历较长的数组得到交集。

大佬指点江山

public static int[] intersect(int[] nums1, int[] nums2) {
    if (nums1.length>nums2.length){
        return intersect(nums2,nums1);
    }
    Map<Integer,Integer> map = new HashMap<>();
    for (int num : nums1) {
        int count = map.getOrDefault(num,0) + 1;
        map.put(num,count);
    }
    int[] arr = new int[nums1.length];
    int index = 0;
    for (int num : nums2) {
        int count = map.getOrDefault(num,0);
        if (count > 0){
            arr[index++] = num;
            count--;
            if (count > 0){
                map.put(num,count);
            }else {
                map.remove(num);
            }
        }
    }
    return Arrays.copyOfRange(arr,0,index);
}

list的效率肯定是低于map的,而我的list还要进行增删操作,故而效率低于大佬的解答。 

2、LeetCode 387.有效的完全平方数

题目

给定一个 正整数 num ,编写一个函数,如果 num 是一个完全平方数,则返回 true ,否则返回 false 。

进阶:不要 使用任何内置的库函数,如  sqrt 。

小编菜解

public static boolean isPerfectSquare(int num) {
    if (num == 1){
        return true;
    }
    for (int i = 2; i < num; i++) {
        if (num%i == 0 && num/i == i){
            return true;
        }
    }
    return false;
}

提示超出时间限制! 

小编菜解进阶版

public static boolean isPerfectSquare(int num) {
    if (num == 1){
        return true;
    }
    int middle = num/2;
    int left = 2;
    int right = num;
    if (num == middle*middle) {
        return true;
    }else if (num > middle*middle){
        left = middle+1;
    }else{
        right = middle - 1;
    }
    for (int i = left; i <= right; i++) {
        if (num%i == 0 && num/i == i){
            return true;
        }
    }
    return false;
}

仍然超出时间限制! 

大佬指点江山

public static boolean isPerfectSquare(int num) {
    if (num == 1){
        return true;
    }
    long left = 2;
    long right = num/2;
    long middle = 0;
    while (left<=right){
        middle = left+(right - left)/2;
        if (num == middle * middle){
            return true;
        }
        if (num > middle * middle){
            left = middle+1;
        }else {
            right = middle - 1;
        }
    }
    return false;
}

真的是菜,什么是二分查找,每次都要进行二分查找,而不是只进行一次,进行一次和不进行,效率上没有任何区别!

3、LeetCode 387.字符串中的第一个唯一字符

题目

给定一个字符串,找到它的第一个不重复的字符,并返回它的索引。如果不存在,则返回 -1。

小编菜解

public static int firstUniqChar(String s) {
    Map<Character,Integer> map = new LinkedHashMap<>();
    //将字符和个数放入map中
    for (int i = 0; i < s.length(); i++) {
        char c = s.charAt(i);
        if (map.containsKey(c)){
            map.put(c,map.get(c)+1);
        }else{
            map.put(c,1);
        }
    }
    //找到第一个值为1的key,因为是LinkedHashMap,所以顺序和字符串顺序一致
    char find = 0;
    for(Map.Entry<Character,Integer> entry : map.entrySet()){
        if (entry.getValue() == 1){
            find = entry.getKey();
            break;
        }
    }
    //再通过找到的第一个唯一字符,找到它的位置
    for (int i = 0; i < s.length(); i++) {
        if (s.charAt(i) == find){
            return i;
        }
    }
    return -1;
}

虽然,写出来了,但肯定不是最优解,麻烦的令人发指。 

大佬指点江山

public static int firstUniqChar(String s) {
    Map<Character,Integer> map = new LinkedHashMap<>();
    //将字符和个数放入map中
    for (int i = 0; i < s.length(); i++) {
        char c = s.charAt(i);
        map.put(c,map.getOrDefault(c,0)+1);
    }
    //再通过找到的第一个唯一字符,找到它的位置
    for (int i = 0; i < s.length(); i++) {
        if (map.get(s.charAt(i))==1){
            return i;
        }
    }
    return -1;
}

大体思路是一样的,只不过我多了一步,不应该啊。

推荐阅读

【100天算法入门 - 每日三题 - Day13】反转字符串、反转字符串中的元音字母、两个数组的交集

【100天算法入门 - 每日三题 - Day12】Nim游戏、3的幂、4的幂

【100天算法入门 - 每日三题 - Day11】丢失的数字、移动零、单词规律

【100天算法入门 - 每日三题 - Day10】二叉树的所有路径、各位相加、丑数 

【100天算法入门 - 每日三题 - Day9】汇总区间、2的幂、有效的字母异位词

【100天算法入门 - 每日三题 - Day8】同构字符串、存在重复元素、翻转二叉树

【100天算法入门 - 每日三题 - Day7】验证回文串、只出现一次的数字、多数元素

...

【100天算法入门 - 每日三题 - Day3】回文数、罗马数字转数字、最大公共前缀

【100天算法入门 - 每日三题 - Day2】二分查找、第一个错误的版本、搜索插入位置

【100天算法入门 - 每日三题 - Day1】二叉树的中序遍历、两数之和、整数反转

以上是关于100天算法入门 - 每日三题 - Day14两个数组的交集有效的完全平方数字符串中的第一个唯一字符的主要内容,如果未能解决你的问题,请参考以下文章

100天算法入门 - 每日三题 - Day13反转字符串反转字符串中的元音字母两个数组的交集

100天算法入门 - 每日三题 - Day11丢失的数字移动零单词规律

100天算法入门 - 每日三题 - Day15判断子序列最长回文数Fizz Buzz

100天算法入门 - 每日三题 - Day16第三大的数字符串中的单词数排列硬币

100天算法入门 - 每日三题 - Day17找到所有数组中消失的数最小操作次数使数组元素相等分发饼干

100天算法入门 - 每日三题 - Day5最后一个单词的长度相同的树买卖股票的最佳时机