Leetcode--哈希表(2)--349,350,202,1,454,15,18

我都准备开始双指针那一节了,才发现双指针里面的内容大多还是前面以及后面章节的内容,比如链表里面的,有些已经做过了,但仔细一看,还存在哈希表的内容,就发觉我忘了一部分,,,哈希表那一节的题,不过剩下的哈希表的题也不是很难,理解了之后,还算简单,虽然看起来挺多的。

349两个数组交集

题目太多,直接分析之后贴代码。
在这里插入图片描述
在这总结的时候我想起来一件事,就是怎么去除重复的,一时间忘记了当时的想法,刚刚去查了一下,set是复用的hashmap的contains()方法,hashmap是不允许有重复的key值出现的,所以这也保证了我们得到的set2中不会有重复的值。

class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        if(nums1 == null || nums1.length == 0 || nums2 == null || nums2.length == 0)
            return new int[0];
        Set<Integer> set1 = new HashSet<>();
        Set<Integer> set2 = new HashSet<>();
        for(int i : nums1)
            set1.add(i);
        for(int i : nums2){
            if(set1.contains(i))
                set2.add(i);//set1是否出现过,出现过就添加
        }
        int res[] = new int[set2.size()];
        int count = 0;
        for(int i : set2) {//set转化为数组
            res[count] = i;
            count++;
        }
        return res;

    }
}

在这里插入图片描述
350题题目给的有点乱,其实就是结果返回重复值,这个重复值还可以重复存在并输出,所以map的设置是用来存放出现的值及次数,res数组来存放要返回的元组,先存好一个nums,然后再去比较,存在就count数减一(跟另一个比,存在就减少一个,减少到0,代表不再有这个key了)。同时,要是存在重复值,就把这个值存在res数组中。

class Solution {
    public int[] intersect(int[] nums1, int[] nums2) {
        if(nums1.length > nums2.length)
            return intersect(nums2, nums1);
        Map<Integer,Integer> map = new HashMap<>();
        for(int i : nums1) {
            int count = map.getOrDefault(i, 0) + 1;
            map.put(i, count);
        }
        int res[] = new int[nums1.length];
        int index = 0;
        for(int i : nums2){//这里的i不是下标,而是nums2的值
            int count2 = map.getOrDefault(i, 0);//判断map中是否存在key,存在返回value(这里的count)
            if(count2 > 0) {//map里面含有这个值,有重复值出现
                res[index] = i;//赶快存进这个数组
                index++;
                count2--;
                if(count2 > 0)
                    map.put(i, count2);
                else
                    map.remove(i);
            }
        }
        return Arrays.copyOfRange(res, 0, index);//nums1为943,,但重复数字只有2个时,第三个就会初始化为0,输出940
//        return res;
    }

202快乐数

在这里插入图片描述
快乐数的难点在于数位分离,做好数位分离。分析题目,就是这个数最后可以变为1就是快乐数。通过不停的循环,看最后是否变为1,而支持这个循环的就是数位分离操作。可以看示例,来一步步操作。

class Solution {
    public boolean isHappy(int n) {
        Set<Integer> set = new HashSet<>();
        while(n != 1 && !set.contains(n)){
            set.add(n);
            n = getNext(n);
        }
        return n == 1;
    }
    public int getNext(int n){//数位分离
        int total = 0;
        while(n > 0){
            int d = n % 10;
            n = n / 10;
            total += d * d;
        }
        return total;
    }
}

1.两数之和

在这里插入图片描述
这里使用map的原因就是他说要返回下标,所以我们要用map来存值和下标。
同时做这个题不能被局限的就是,,和—>减。后面几个求和也会用到。

class Solution {
    public int[] twoSum(int[] nums, int target) {
        if(nums == null || nums.length == 0)
            return new int[2];

        HashMap<Integer, Integer> map = new HashMap<>();//key存值,value存下标
        int res[] = new int[2];
        for(int i = 0; i < nums.length; i++){
            int temp = target - nums[i];
            if(map.containsKey(temp)){
                res[0] = i;//题目说顺序无所谓
                res[1] = map.get(temp);//获取temp这个key对应的value值(也就是下标)
            }
            map.put(nums[i], i);
        }
        return res;
    }
}

# 1.两数之和
四数相加在于,不需要考虑数值是否存在重复的情况,因为有四个数组,就随意搭配,搭配到能出现和为0的情况,然后记录下来次数,最后返回的也是次数(一个int)。做过前面的题,就可以知道,和也是减,所以利用这个想法去求解。

class Solution {
    public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
        Map<Integer, Integer> map = new HashMap<>();//key存放两数之和,value计算两数之和出现的次数
        for(int i : nums1){
            for(int j : nums2){
                if(map.containsKey(i+j))
                    map.put(i+j, map.get(i+j) + 1);//相同的和再次出现就加一
                else
                    map.put(i+j, 1);
            }
        }
        //计算剩下两数之和,在map中寻找是否存在相加为0的情况
        int res = 0;//计算元组的次数
        for(int m : nums3){
            for(int n: nums4){
                int temp = 0 - (m+n);
                if(map.containsKey(temp))
                    res += map.get(temp);
            }
        }
        return res;
    }
}

在这里插入图片描述
在这里插入图片描述
三数之和,四数之和,难点在于,不包含重复的四元组,最后返回的也是四元组。这里也是用的和即是减,但没有用哈希表,而是双指针,所以这个题也属于双指针系列。通过不停的的双指针:left和right的移动来计算这个最终的值,同时在指针移动过程中来排除相同的数,当然以上的操作都基于一个最主要的,返回的是元组,不是下标,所以排好序,才能用双指针,这样才能在移动过程中去排除相同的数。

三数之和
class Solution {
    public List<List<Integer>> threeSum(int[] nums) {//注意,这儿给了个二维列表
        List<List<Integer>> res = new ArrayList<>();//存放二维列表最终结果
        Arrays.sort(nums);//排序
        for(int i = 0; i < nums.length; i++){
            if(nums[i] > 0) return res;
            if(i > 0 && nums[i] == nums[i-1]) continue;//排除移动i的时候,出现重复值的情况
            int left = i + 1;
            int right = nums.length - 1;
            while(right > left){
                int sum = nums[i] + nums[left] + nums[right];//此处算的是三数之和,不是下标之和
                if(sum > 0) right--;
                else if (sum < 0) left++;
                else{
                    res.add(Arrays.asList(nums[i], nums[left], nums[right]));
                    while(left < right && nums[right] == nums[right-1]) right--;//去掉重复的值,前面排好序了
                    while(left < right && nums[left] == nums[left+1]) left++;
                    right--;//移动到下一位,进行下一轮i的匹配
                    left++;
                }
            }
        }
        return res;

    }
}
四数之和(同理,五个数,六个数)
class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {//理解了三数之和,就可以理解四数之和
        List<List<Integer>> res = new ArrayList<>();
        Arrays.sort(nums);

        for(int i = 0; i < nums.length; i++){
            if(i > 0 && nums[i] == nums[i-1]) continue;
            for(int j = i+1; j < nums.length; j++){
                if(j > i+1 && nums[j] == nums[j-1]) continue;
                int left = j + 1;
                int right = nums.length - 1;
                while(left < right){
                    int temp = nums[left] + nums[right] + nums[i] + nums[j];
                    if(temp > target) right--;
                    else if(temp < target) left++;
                    else{
                        res.add(Arrays.asList(nums[i],nums[j],nums[left], nums[right]));
                        while(left < right && nums[left] == nums[left+1]) left++;
                        while(left < right && nums[right] == nums[right-1]) right--;
                        right--;
                        left++;
                    }
                }
            }
        }
        return res;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

飞翔的胖迪

相逢即是有缘,不打赏给个赞也行

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值