day7任务

没封面不好看感觉........

今天下班太晚了,能做到哪里是哪里,就看下思路大概对着码一下练练手。mark一下,周末补回来。


1.四数相加II:代码随想录 (programmercarl.com)

力扣链接:. - 力扣(LeetCode)

这个题简单点的原因是没有去重的操作,给了四个数组看似很麻烦其实很方便,四数相加很容易变为两数相加,这两个数就是分别从A+B和C+D中集合在一起的。

具体看代码,记录下,详细思路见网站和B站链接。学透哈希表,map使用有技巧!LeetCode:454.四数相加II_哔哩哔哩_bilibili

package LuStudy;

import java.util.HashMap;
import java.util.Map;

/*
 *  四数相加II
 * 
 *  https://leetcode.cn/problems/4sum-ii/
 */
public class _7_1FourNumbersEachPlus {
    private static int getFourPlus(int[] numsA, int[] numsB, int[] numsC, int[] numsD) {
        Map<Integer, Integer> map = new HashMap<>();
        for (int a : numsA) {
            for (int b : numsB) {
                map.put(a + b, map.getOrDefault(a + b, 0) + 1);
            }
        }
        int res = 0;
        for (int c : numsC) {
            for (int d : numsD) {
                res += map.getOrDefault(0 - c - d, 0);// 这两边default的含义不一样
            }
        }
        return res;
    }

    public static void main(String[] args) {
        int[] numsA = { 1, 2 };
        int[] numsB = { -2, -1 };
        int[] numsC = { -1, 2 };
        int[] numsD = { 0, 2 };
        System.out.println(getFourPlus(numsA, numsB, numsC, numsD));
    }
}

2.赎金信:代码随想录 (programmercarl.com)

力扣链接:. - 力扣(LeetCode)

这个跟异位字母词那道题比较像,而且只出现小写字母,所以可以定义一个26大小的数组,查询也比较方便,修改对应位置的值也直接覆盖,不会删除数组元素,所以可以用数组解题。

map也不是不可以,就像卡哥说的,map比较占用内存空间。

因为map要维护红黑树或者哈希表,而且还要做哈希函数,是费时的!数据量大的话就能体现出来差别了。 所以数组更加简单直接有效!

只有最后的判断条件不同,其他操作都一样。

class Solution {
    public boolean canConstruct(String ransomNote, String magazine) {
        // shortcut
        if (ransomNote.length() > magazine.length()) {
            return false;
        }
        // 定义一个哈希映射数组
        int[] record = new int[26];

        // 遍历
        for(char c : magazine.toCharArray()){
            record[c - 'a'] += 1;
        }

        for(char c : ransomNote.toCharArray()){
            record[c - 'a'] -= 1;
        }
        
        // 如果数组中存在负数,说明ransomNote字符串中存在magazine中没有的字符
        for(int i : record){
            if(i < 0){
                return false;
            }
        }

        return true;
    }
}

周末再粘一个map的用法,大概就是先遍历杂志的单词,统计value。再遍历赎金数组,对应的value减一下,最后遍历所有value,有<0的就是false了。否则就true。大概是这个思路。


这两个题没时间写了,再看下思路。


3.三数之和:代码随想录 (programmercarl.com)

力扣链接:. - 力扣(LeetCode)

先是看了提醒,说双指针比较容易。还没细究原因。但是一看题目三数之和确实知道双指针大概怎么写了。不过想和写还是两说,最好自己写下,周末补上。

双指针法:外层有个for循环,再在for内层定义左右双指针。循环遍历,有符合条件的记录下数组[i,left,right]。大概就是这个思路。还有个细节,for只循环到倒数第三个,即i<nums.length-2。因为到倒数第三个了,双指针只有一个选择,判断下满足不满足就行了。

再看了下思路:数组先排序一下。因为不用输出下标,只输出数的组合。排序后外层for照常定义,内层可以定义左指针最左即i+1,外层可以定义最右len-1(下标),这样子看target-i剩下的数

如果nums[i] + nums[left] + nums[right] > 0 就说明 此时三数之和大了,因为数组是排序后了,所以right下标就应该向左移动,这样才能让三数之和小一些。

如果 nums[i] + nums[left] + nums[right] < 0 说明 此时 三数之和小了,left 就向右移动,才能让三数之和大一些,直到left与right相遇为止。

代码(双指针法)粘一下:

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> result = new ArrayList<>();
        Arrays.sort(nums);
	// 找出a + b + c = 0
        // a = nums[i], b = nums[left], c = nums[right]
        for (int i = 0; i < nums.length; i++) {
	    // 排序之后如果第一个元素已经大于零,那么无论如何组合都不可能凑成三元组,直接返回结果就可以了
            if (nums[i] > 0) { 
                return result;
            }

            if (i > 0 && nums[i] == nums[i - 1]) {  // 去重a
                continue;
            }

            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 {
                    result.add(Arrays.asList(nums[i], nums[left], nums[right]));
		    // 去重逻辑应该放在找到一个三元组之后,对b 和 c去重
                    while (right > left && nums[right] == nums[right - 1]) right--;
                    while (right > left && nums[left] == nums[left + 1]) left++;
                    
                    right--; 
                    left++;
                }
            }
        }
        return result;
    }
}

4.四叔之和:代码随想录 (programmercarl.com)

力扣链接:. - 力扣(LeetCode)

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值