力扣刷题篇之哈希表2

系列文章目录


目录

系列文章目录

前言

一、哈希表与统计

二、哈希表与前缀和

总结


前言

 本系列是个人力扣刷题汇总,本文是哈希表。刷题顺序按照[力扣刷题攻略] Re:从零开始的力扣刷题生活 - 力扣(LeetCode)


一、哈希表与统计

排序后,用两个指针,类似于窗口。没用哈希表 

// class Solution {
//     public int findLHS(int[] nums) {
//         Arrays.sort(nums);
//         int begin = 0,res = 0;
//         for(int end = 0;end < nums.length;end++){
//             while(nums[end] - nums[begin] > 1)
//                  begin++;
//             if(nums[end] - nums[begin] == 1)
//               res = Math.max(res,end - begin + 1);
//         }
//         return res;
//     }
// }

class Solution {
    public int findLHS(int[] nums) {
        Arrays.sort(nums);
        int begin =0;
        int res=0;
        for(int end=0;end<nums.length;end++){
            if(nums[end]-nums[begin]>1){
                begin++;
            }
            if(nums[end]-nums[begin]==1){
                res = Math.max(res,end-begin+1);
            }
        }
        return res;
    }
}

 

 用哈希表

class Solution {
    public int findLHS(int[] nums) {
        HashMap<Integer,Integer> cnt=new HashMap<>();
        for(int num:nums){
            cnt.put(num,cnt.getOrDefault(num,0)+1);
        }
        int res=0;
        for(int key : cnt.keySet()){
            if(cnt.containsKey(key+1)){
                res=Math.max(res,cnt.get(key)+cnt.get(key+1));
            }
        }
        return res;
    }
}

 

 辅助数组:通过使用一个辅助数组 map 来记录 nums1 数组中每个元素的出现次数,并根据 map 数组的信息,遍历 nums2 数组,找出两个数组的交集,并将交集存储在 nums2 数组中。

class Solution {
    public int[] intersect(int[] nums1, int[] nums2) {
        int[] map=new int[1001];
        int count=0;
        for(int num:nums1)
        {
            map[num]++;
        }
        for(int num:nums2)
        {
            if(map[num]>0)
            {
                nums2[count++]=num;
                map[num]--;
            }
        }
        return Arrays.copyOfRange(nums2,0,count);
    }
}

 

 哈希表:使用哈希表记录了 nums1 数组中每个元素及其出现次数,然后遍历 nums2 数组,根据哈希表的信息找到交集的元素,并将交集存储在 res 列表中。最后,将 res 列表转换为数组并返回。

class Solution {
    public int[] intersect(int[] nums1, int[] nums2) {
        Map<Integer,Integer> map = new HashMap<>();
        List<Integer> res = new ArrayList<>();
        for(int i : nums1){
            if(!map.containsKey(i)) map.put(i,1);
            else map.put(i,map.get(i)+1);
        }
        for(int i : nums2){
            if(!map.containsKey(i)) continue;
            else if(map.get(i) > 0){
                map.put(i,map.get(i)-1);
                res.add(i);
            }
        }
        int[] array = new int[res.size()];
      for (int i = 0; i < res.size(); i++) {
              array[i] = res.get(i);
        }
        return  array;
    }
}

 

  • 创建一个 HashMap 对象 map,用于记录每个断点位置出现的次数。
  • 创建一个变量 max,用于记录最大的断点次数。
  • 定义方法 leastBricks,接受一个二维列表 wall,表示砖墙的布局。方法返回穿过砖墙的最少砖块数。
  • 遍历砖墙的每一行 row,调用方法 processRow 处理每一行的砖块布局。
  • 返回砖墙的行数减去最大断点次数,即穿过砖墙的最少砖块数。
  • 定义方法 processRow,接受一个列表 row,表示砖墙的一行砖块布局。
  • 初始化变量 rowSum 为第一个砖块的宽度,表示当前行的砖块边界位置。
  • 遍历当前行的每个砖块,从第二个砖块开始。
    • 获取 rowSum 在 map 中对应的值 f,如果该值不存在,则默认为 0。
    • 将 rowSum 在 map 中的值加 1,并更新 map
    • 如果当前 f 值大于 max,则更新 max
    • 将 rowSum 累加当前砖块的宽度,得到下一个断点位置。
  • 方法执行完毕后,map 中记录了所有断点位置出现的次数,max 记录了最大的断点次数。

遍历砖墙的每一行,记录每个断点位置出现的次数,最后返回穿过砖墙的最少砖块数。通过使用哈希表 map 记录断点位置的出现次数,可以有效计算最少砖块数。

class Solution{
    private final Map<Integer, Integer> map = new HashMap<>();
    private int max = 0;

    public int leastBricks(List<List<Integer>> wall){
        for (List<Integer> integers : wall){
            processRow(integers);
        }
        return wall.size() - max;
    }

    public void processRow(List<Integer> row){
        int rowSum = row.get(0);
        for (int j = 1; j < row.size(); j++){
            int f = map.getOrDefault(rowSum, 0) + 1;
            map.put(rowSum, f);
            if (f > max) max = f;
            rowSum += row.get(j);
        }
    }
}

 

 

 

class Solution {
   public List<List<String>> findDuplicate(String[] paths) {
        HashMap<String, List<String>> contentToFileNames = new HashMap<>();//文件内容到文件全路径的映射
        List<List<String>> res = new ArrayList<>();
        for (String path : paths) {
            char[] p = path.toCharArray();
            int i = 0;
            while (i < p.length && p[i] != ' ') {//路径名
                i++;
            }
            String pathName = path.substring(0, i);
            i++;
            while (i < p.length) {
                int j = i;
                while (i < p.length && p[i] != '(') {//文件名
                    i++;
                }
                String fileName = path.substring(j, i);
                i++;
                j = i;
                while (i < p.length && p[i] != ')') {//内容
                    i++;
                }
                String fileContent = path.substring(j, i);
                //路径名+文件名可以唯一地确定一个文件
                String fullPath = new StringBuilder(pathName).append("/").append(fileName).toString();
                List<String> fileNameList = contentToFileNames.getOrDefault(fileContent, new ArrayList<>());
                fileNameList.add(fullPath);
                contentToFileNames.put(fileContent, fileNameList);
                i += 2;
            }
        }
        Set<String> keys = contentToFileNames.keySet();
        for (String key : keys) {
            List<String> fullPaths = contentToFileNames.get(key);
            if (fullPaths.size() > 1) {
                res.add(fullPaths);
            }
        }
        return res;
    }
}

class Solution {
    public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
        int[] max_min_1 = getMaxMin(nums1);
        int[] max_min_2 = getMaxMin(nums2);
        int[] max_min_3 = getMaxMin(nums3);
        int[] max_min_4 = getMaxMin(nums4);
        int res = 0;
        int max = Math.max(max_min_1[1] + max_min_2[1], -(max_min_3[0]+max_min_4[0]));
        int min = Math.min(max_min_1[0] + max_min_2[0], -(max_min_3[1]+max_min_4[1]));

        int[] arr = new int[max-min+1];
        for (int i : nums1) {
            for (int j : nums2) {
                arr[i+j -min]++;
            }
        }
        
        for (int i : nums3) {
            for (int j : nums4) {
                res += arr[-(i+j)-min];
            }
        }

        return res;
    }

    private int[] getMaxMin(int[] nums) {
        int max = nums[0];
        int min = nums[0];
        for (int num : nums) {
            if (max<num){
                max = num;
            }
            if (min>num){
                min = num;
            }
        }
        return new int[]{min, max};
    }
}

 

 

二、哈希表与前缀和

 

class Solution {
    public int subarraySum(int[] nums, int k) {
        //记录和为k的子数组的数量
        int count = 0;
        //前缀和
        int preSum = 0;
        //存储前缀和出现的次数
        Map<Integer,Integer> map = new HashMap<>();
        //特殊处理
        map.put(0,1);
        for (int i = 0; i < nums.length; i++) {
            preSum += nums[i];
            //满足条件的前缀和
            if (map.containsKey(preSum - k)){
                count += map.get(preSum - k);
            }
            //存储前缀和出现的次数
            map.put(preSum,map.getOrDefault(preSum,0) + 1);
        }
        return count;
    }
}

 

class Solution {
    public boolean checkSubarraySum(int[] nums, int k) {
        int n = nums.length;
        int[] prefix = new int[n+1];
        for (int i=1;i<n+1;i++) {
            prefix[i] = nums[i-1]+prefix[i-1];
        }

        HashSet<Integer> set = new HashSet();
        for (int i=2;i<=n;i++) {
            set.add(prefix[i-2]%k);
            if (set.contains(prefix[i]%k))
                return true;
        }
        return false;
    }
}

 

class Solution {
    public int findMaxLength(int[] nums) {
        if(nums.length == 0 || nums.length == 1) 
            return 0;

        int maxLength = 0;
        int[] arr = new int[2*nums.length+1];
        
        for( int i = 0; i < arr.length; i++) 
            arr[i] = -2;
        
        arr[nums.length]=-1;
        int counter = nums.length;
        
        for(int i = 0; i < nums.length; i++){
            counter+=nums[i]*2-1;
            if(arr[counter] == -2){
                arr[counter] = i;
            }else{
                maxLength = Math.max(maxLength, i-arr[counter]);
            }                
        }
        return maxLength;
    }
}
 

 


总结

待修改。。。

  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值