代码随想录之哈希表(力扣题号)

242. 有效的字母异位词

在这里插入图片描述
直接用数组模拟哈希表
只有小写字母,开26的数组就可以了

class Solution {
    public boolean isAnagram(String s, String t) {
        //24-28
        int[] hash = new int[26];
        Arrays.fill(hash,0);
        for(int i=0;i<s.length();i++){
            hash[s.charAt(i)-'a']++;
        }
        for(int i=0;i<t.length();i++){
            hash[t.charAt(i)-'a']--;
        }
        for(int i=0;i<hash.length;i++){
            if(hash[i]!=0) return false;
        }
        return true;
    }
}

49. 字母异位词分组

在这里插入图片描述
思路也是用hashmap,但是java的操作没有很熟练,遇到很多问题,最后看了题解还是没能一次性写完,中间还看了两次,之后需要再练习几次

class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        //01-29
        Map<String, List<String>> mp= new HashMap<>();      
        for(int i=0;i<strs.length;i++){
            char[] arr = strs[i].toCharArray();
            Arrays.sort(arr);
            String key = new String(arr);
            List<String> list = mp.getOrDefault(key,new ArrayList<String>());
            list.add(strs[i]);
            mp.put(key,list);
        }
        return new ArrayList<List<String>>(mp.values());

    }
}

时间复杂度:
O(nklogk),其中 n 是 strs 中的字符串的数量,k 是 strs 中的字符串的的最大长度。需要遍历 n 个字符串,对于每个字符串,需要 O(klogk) 的时间进行排序以及 O(1) 的时间更新哈希表,因此总时间复杂度是 O(nklogk)。

空间复杂度:O(nk),其中 n 是 strs中的字符串的数量,k 是 strs 中的字符串的的最大长度。需要用哈希表存储全部字符串。

15 三数之和

在这里插入图片描述
在这里插入图片描述

这题和之前牛客做过的一样,还是一样的思路:在两数之和的基础上遍历,然后用set去重,这题不要求输出结果也排序。但是这题的数据范围更大,按照之前的写法会超时,所以加了个排序,然后如果是重复的数字就跳过遍历。

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        //57-40
        Arrays.sort(nums);
        List<List<Integer>> res= new ArrayList<List<Integer>>();
        List<List<Integer>> ress= new ArrayList<List<Integer>>();
        for(int i=0;i<nums.length;i++){
            int target = -nums[i];
            if(i>0&&nums[i]==nums[i-1]) continue;//跳过遍历,否则会超时
            Map<Integer,Integer> mp = new HashMap<>();
            for(int j = i+1;j<nums.length;j++){
                if(mp.containsKey(nums[j])){
                    List<Integer> row = new ArrayList<>();
                    row.add(nums[i]);
                    row.add(target-nums[j]);
                    row.add(nums[j]);
                    row.sort((a,b)->a-b);  
                    res.add(row);
                }
                mp.put(target-nums[j],j);              
            }
        }
    Set<List<Integer>> s = new HashSet<List<Integer>>();
    for(int i=0;i<res.size();i++){
        s.add(res.get(i));
    }
    for( List<Integer> r:s){
        ress.add(r);
    }
        return ress;
    }
}

但是这样还是三重循环,时间复杂度还是N的三次方。
可以继续改进:当a+b+c=0的时候,第二层b’>b,要让条件满足的c‘一定<c,所以可以让第三层指针从右往左,和第二层的指针合并为一层,将时间复杂度降为O(N^2)

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        //57-40
        Arrays.sort(nums);
        List<List<Integer>> res= new ArrayList<List<Integer>>();
        for(int i=0;i<nums.length-2;i++){
            int target = -nums[i];
            if(i>0&&nums[i]==nums[i-1]) continue;
            int left = i+1;
            int right = nums.length-1;
            while(left<right){
                if(nums[left]+nums[right]<target) left++;
                else if(nums[left]+nums[right]>target) right--;
                else{
                    while(left + 1 < right && nums[left] == nums[left + 1])
                        //去重
                        left++;
                    while(right - 1 > left && nums[right] == nums[right - 1])
                        //去重
                        right--;
                    List<Integer> row = new ArrayList<>();
                    row.add(nums[i]);
                    row.add(nums[left]);
                    row.add(nums[right]);
                    res.add(row);
                    left++;
                    right--;
                }
            }                         
        }

        return res;

    }
}

18 四数之和

在这里插入图片描述
在这里插入图片描述
和三数之和的思路一样,就是多了一层循环,但是四数有一个坑点在于用int会溢出,要转换成long

class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        //47-04
        List<List<Integer>> res = new ArrayList<List<Integer>>();
        Arrays.sort(nums);
        for(int i=0;i<nums.length-3;i++){
            if(i>0&&nums[i]==nums[i-1]) continue;
            for(int j = i+1;j<nums.length-2;j++){
                if(j>i+1&&nums[j]==nums[j-1]) continue;
                int left = j+1;
                int right = nums.length-1;
                while(left<right){
                //注意要转换成long,否则会溢出
                    long sum = (long)nums[i]+(long)nums[j]+(long)nums[left]+(long)nums[right];
                    if(sum>target) right--;
                    else if(sum<target) left++;
                    else{
                        List<Integer> tmp = new ArrayList<Integer>();
                        tmp.add(nums[i]);
                        tmp.add(nums[j]);
                        tmp.add(nums[left]);
                        tmp.add(nums[right]);
                        res.add(tmp);
                        //可以用一句解决
                        //res.add(Arrays.asList(nums[i], nums[j], nums[left], nums[right]));
                        while(left<right&&nums[left+1]==nums[left]) left++;
                        while(left<right&&nums[right-1]==nums[right]) right--;
                        left++;
                        right--;
                    }
                }
            }
        }
        return res;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值