Day07 HashTable-勒索信+3/4数之和(可下标重复/不可下标重复)+从这天开始每天整理更新APIs

英语角
    distinct integers 不同整数 35
    Spiral Matrix 螺旋矩阵 59 
    contiguously 连续地        
    scattered 分散的
    programming context 编程上下文
    traversal 遍历
    Variants 变体(Circular and Doubly Linked Variants: circular linked lists& doubly linked lists
    intersect 交叉
    anagram  相同字母异序词
    index 复数:indices
    tuple 元组
    triplet 三胞胎/三连音 
    quadruplet 四胞胎
    ransom 赎金
    ransom note 勒索信

APIs:
String API
    1.s.length
    2.s.charAt()

    
Array
    1.Arrays.sort(arr);
    2.Arrays.asList(arr)
    
List/Set/Map
    List:
        1.定义二维list;List<List<Integer>> res = new ArrayList<>();
        
    Set:
        1.size();
        2.add(int);
        3.contains()
        4.将结果集合转为数组:
            (1)resSet.stream().mapToInt(x -> x).toArray();
            (2)另外申请一个数组存放setRes中的元素,最后返回数组
                int[] arr = new int[resSet.size()];
                int j = 0;
                for(int i : resSet){
                    arr[j++] = i;
                }
    
    Map:
        1.getOrderDefault(Object key,Integer default number):
            key:要检索的键。
            defaultValue:如果 Map 中不存在该键,则返回此默认值。

    3.6 454. 4Sum II
        Given four integer arrays nums1, nums2, nums3, and nums4 all of length n, return the number of tuples (i, j, k, l) such that:
        0 <= i, j, k, l < n
        nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0
        public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
            int count = 0;
            Map<Integer,Integer> map = new HashMap<Integer,Integer>();
            for(int i : nums1){
                for(int j:nums2){
                    int sum = i+j;
                    map.put(sum,map.getOrDefault(sum,0)+1);
                }
            }
            for(int i : nums3){
                for(int j:nums4){
    //                int sum = -(i+j);
    //                if(map.containsKey(sum)){
    //                    count += map.get(sum);
    //                }
                    //可简化为:返回key=-(i+j)对应的value,如果没有,则返回0
                    count  += map.getOrDefault(0-(i+j),0);
                }
            }
            return count;
        }
    3.7 383. Ransom Note
        Given two strings ransomNote and magazine, return true if ransomNote can be constructed by using the letters from magazine and false otherwise.
        Each letter in magazine can only be used once in ransomNote.
        思路和anagram差不多
        public boolean canConstruct(String ransomNote, String magazine) {
            int[] arr = new int[26];
            for (int i = 0; i < magazine.length(); i++) {
                arr[magazine.charAt(i)-'a']++;
            }
            for (int i = 0; i < ransomNote.length(); i++) {
                arr[ransomNote.charAt(i)-'a']--;
            }
            for(int i : arr){
                if(i < 0) return false;
            }
            return true;
        }
    3.8 15. 3Sum
        Given an integer array nums, return all the triplets [nums[i], nums[j], nums[k]] such that i != j, i != k, and j != k, and nums[i] + nums[j] + nums[k] == 0.
        Notice that the solution set must not contain duplicate triplets.
        哈希法不便于去重,用双指针法。
        审题!!这道题我一开始理解错了,以为是三个数组,分别需要从三个数组中找到下标不同的满足条件的三个元素。审题很重要!!!
        自己写的时候犯了一些错误,主要集中在有结果后的部分。
            得到结果后需要做三件事:去重left,去重right,left、right往前进一步。如果去重后忘记继续走,那么循环将无法结束。
            并且得到结果后的部分都是写在sum==0条件的执行语句中的。不然会导致left/right在sum!=0的时候重复往下走,可能会导致漏解(比如leetcode隐藏测试{-1,-1,0,1}.
        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;
                //对nums[i]去重
                if(i > 0 && nums[i] == nums[i-1]) continue;
                int left = i+1;
                int right = nums.length-1;
                while (left < right){
                    //先返回一个结果
                    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]));
                        //这后面是得到一个结果后做的操作:去重left,去重right,left、right往前进一步
                        //再去重left right
                        while (left < right && nums[right] == nums[right-1]){
                            right--;
                        }
                        while (left < right && nums[left] == nums[left+1]){
                            left++;
                        }
                        //去重结束以后往下走!!!这步不能忘
                        left++;
                        right--;
                    }
                }
            }
            return res;
        }
        编写测试类的时候顺便复习了一下三种遍历方法中的iterator遍历和增强for循环遍历,并且这是二重list:
        public static void main(String[] args) {
                threeSumNoRepeat t = new threeSumNoRepeat();
                int[] ints = {-1,-1,1,0};
                List<List<Integer>> res = t.threeSum(ints);

                //遍历方法1:增强for循环
                for (List<Integer> innerList : res) {
                    System.out.print("[");
                    for (Integer num : innerList) {
                        System.out.print(num + (innerList.indexOf(num) < innerList.size() - 1 ? ", " : ""));
                    }
                    System.out.println("]");
                }
                //遍历方法2:iterator
        //        Iterator<List<Integer>> outerIterator = res.iterator();
        //        while (outerIterator.hasNext()) {
        //            List<Integer> innerList = outerIterator.next();
        //            Iterator<Integer> innerIterator = innerList.iterator();
        //
        //            System.out.print("[");
        //            while (innerIterator.hasNext()) {
        //                Integer num = innerIterator.next();
        //                System.out.print(num + (innerIterator.hasNext() ? ", " : ""));
        //            }
        //            System.out.println("]");
        //        }
        }
        
        
    3.9 18. 4Sum
        Given an array nums of n integers, return an array of all the unique quadruplets [nums[a], nums[b], nums[c], nums[d]] such that:
        0 <= a, b, c, d < n
        a, b, c, and d are distinct.
        nums[a] + nums[b] + nums[c] + nums[d] == target
        You may return the answer in any order.
        这题写的时候错误点在于:int sum = nums[i] + nums[j] + nums[left] + nums[right];应该写在while(left<right)执行条件内,不然会导致left下标溢出。
        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(nums[i] > target && (nums[i]>=0 || target>0)) return res;
    if(nums[i] > 0  && nums[i] > target) return res;
    if(i>0 && nums[i] == nums[i-1]) continue;
    for (int j = i+1; j < nums.length; j++) {
        //二级剪枝+二级去重
        //if(nums[i]+nums[j] > target && (nums[i]+nums[j]>=0 || target>0)) return res;
        if(nums[i]+nums[j] > 0 && nums[i]+nums[j] > target) return res;
        //因为后面要比较j-1,所以要保证j > i+1
        if(j > i+1 && nums[j] == nums[j-1]) continue;
        int left = j+1;
        int right = nums.length-1;
        while(left<right){
            int sum = nums[i] + nums[j] + nums[left] + nums[right];
            if (sum<target){
                left++;
            }else if(sum>target){
                right--;
            }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--;
                left++;
                right--;
            }
        }
    }
}
return res;

        }    

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值