IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 代码随想录——哈希表 -> 正文阅读

[数据结构与算法]代码随想录——哈希表

题目来自:https://www.programmercarl.com/%E5%93%88%E5%B8%8C%E8%A1%A8%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html#%E5%93%88%E5%B8%8C%E8%A1%A8

一、数组作为哈希表

242. 有效的字母异位词

https://leetcode-cn.com/problems/valid-anagram/

	public boolean isAnagram(String s, String t) {

        int[] record = new int[26];
        for (char c : s.toCharArray()) {
            record[c - 'a'] += 1;
        }
        for (char c : t.toCharArray()) {
            record[c - 'a'] -= 1;
        }
        for (int i : record) {
            if (i != 0) {
                return false;
            }
        }
        return true;
    }

383. 赎金信

https://leetcode-cn.com/problems/ransom-note/

	public boolean canConstruct(String ransomNote, String magazine) {
		
		int[] record = new int[26];
		for(char c : magazine.toCharArray()){
			record[c - 'a']++;
		}
		
		for(char c : ransomNote.toCharArray()){
			record[c - 'a']--;
			if(record[c - 'a'] < 0) return false;
		}
		
		return true;
	}

49. 字母异位词分组(未完成)

https://leetcode-cn.com/problems/group-anagrams/

438. 找到字符串中所有字母异位词

https://leetcode-cn.com/problems/find-all-anagrams-in-a-string/

	public List<Integer> findAnagrams(String s, String p) {
		int sLen = s.length(), pLen = p.length();

        if (sLen < pLen) {
            return new ArrayList<Integer>();
        }
        
        List<Integer> ans = new ArrayList<Integer>();

        int[] pCount = new int[26];
        int[] sCount = new int[26];
        
        //先把第一组数比较一下
        for(int i=0; i<pLen; i++){
        	pCount[p.charAt(i)-'a']++;
        	sCount[s.charAt(i)-'a']++;
        }
        //第一组数一样就放进ans
        if (Arrays.equals(sCount, pCount)) {
            ans.add(0);
        }
        //然后每次后面加一个,前面减一个
        for (int i = 0; i < sLen - pLen; ++i) {
        	sCount[s.charAt(i)-'a']--;
        	sCount[s.charAt(i+pLen)-'a']++;
        	
        	if(Arrays.equals(sCount, pCount)){
        		ans.add(i+1);//注意这里是i加1!虽然i从0开始,但是0位置上已经判断过了
        	}
        }          
        return ans;
	}

二、set作为哈希表

349. 两个数组的交集

https://leetcode-cn.com/problems/intersection-of-two-arrays/

  1. 两个哈希
  2. 排序
	/**
	 * 执行用时:2 ms, 在所有 Java 提交中击败了93.30%的用户
	 * 内存消耗:41 MB, 在所有 Java 提交中击败了42.74%的用户
	 */
	public int[] intersection2(int[] nums1, int[] nums2) {
		Set<Integer> set1 = new HashSet<>();
		Set<Integer> set2 = new HashSet<>();
		//遍历数组1,把数加紧哈希1
		for(int i : nums1){
			set1.add(i);
		}
		//遍历数组2,数组里里有,加进哈希2
		for(int i : nums2){
			if(set1.contains(i)){
				set2.add(i);
			}
		}
		//把哈希2转化成数组
		int[] ans = new int[set2.size()];
		int index = 0;
		for(int i: set2){
			ans[index] = i;
			index++;
		}
		return ans;
	}
	/**
	 * 执行用时:2 ms, 在所有 Java 提交中击败了93.30%的用户
	 * 内存消耗:41.3 MB, 在所有 Java 提交中击败了30.39%的用户
	 */
	public int[] intersection(int[] nums1, int[] nums2) {
		Arrays.sort(nums1);
        Arrays.sort(nums2);
        int length1 = nums1.length, length2 = nums2.length;
        int[] intersection = new int[length1 + length2];
        int index = 0, index1 = 0, index2 = 0;

        while(index1 < length1 && index2 < length2){
        	int num1 = nums1[index1], num2 = nums2[index2];
        	if(num1 == num2){
        		// 保证加入元素的唯一性
                if (index == 0 || num1 != intersection[index - 1]) {
                    intersection[index++] = num1;
                }
                index1++;
                index2++;
        	}else if(num1 > num2){
        		index2++;
        	}else{
        		index1++;
        	}       	
        }       
        return Arrays.copyOfRange(intersection, 0, index);
	}

三、map作为哈希表

350. 两个数组的交集 II

https://leetcode-cn.com/problems/intersection-of-two-arrays-ii/
和上题方法类似

  1. 哈希
  2. 排序双指针
	/**
	 * 执行用时:2 ms, 在所有 Java 提交中击败了85.62%的用户
	 * 内存消耗:41.5 MB, 在所有 Java 提交中击败了18.33%的用户
	 */
	public int[] intersect2(int[] nums1, int[] nums2) {
		Map<Integer, Integer> map = new HashMap<Integer, Integer>();
		//1.遍历数组1把哈希映射放进去
		for(int num:nums1){
			int count = map.getOrDefault(num, 0) + 1;
			map.put(num, count);
		}
		//2.创造数组ans,最终答案不会比ans长
		int[] ans = new int[nums1.length];
        int index = 0;
		//3.遍历数组2中每一个数,哈希中不存在或为0就不放入ans中
        for(int num:nums2){
        	int count = map.getOrDefault(num, 0);//当前这个数在哈希里的值,没有就是0
        	if(count > 0){//大于0才放
        		ans[index++] = num;
        		count--;//减去放的这个
        		if(count == 0){//如果减完这一个就没了,连key一起删了
        			map.remove(num);
        		}else{//如果减完还有,再放回去
        			map.put(num, count);
        		}
        	}
        }
        return Arrays.copyOfRange(ans, 0, index);
	}
	
	
	
	/**
	 * 执行用时:2 ms, 在所有 Java 提交中击败了85.62%的用户
	 * 内存消耗:41.7 MB, 在所有 Java 提交中击败了6.10%的用户
	 */
	public int[] intersect(int[] nums1, int[] nums2) {
		Arrays.sort(nums1);
        Arrays.sort(nums2);
        int length1 = nums1.length, length2 = nums2.length;
        int[] intersection = new int[length1 + length2];
        int index = 0, index1 = 0, index2 = 0;

        while(index1 < length1 && index2 < length2){
        	int num1 = nums1[index1], num2 = nums2[index2];
        	if(num1 == num2){
        		intersection[index++] = num1;
                index1++;
                index2++;
        	}else if(num1 > num2){
        		index2++;
        	}else{
        		index1++;
        	}       	
        }       
        return Arrays.copyOfRange(intersection, 0, index);
	}

454. 四数相加 II

https://leetcode-cn.com/problems/4sum-ii/
分成两拨,有点像两数之和

	public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
		int ans = 0;
		Map<Integer, Integer> map = new HashMap<Integer, Integer>();
		//把1和2的和以及个数存一下
		for(int i : nums1){
			for(int j :nums2){
				int sum12 = i+j;
				int count1 = map.getOrDefault(sum12, 0) + 1;
				map.put(sum12, count1);
			}
		}
		//遍历3和4的和看有没有合适的
		for(int i : nums3){
			for(int j : nums4){
				int sum34 = i+j;
				int neednum = 0 - sum34;
				//如果存在所需要的这个数
				if(map.containsKey(neednum)){
					ans+=map.get(neednum);
				}
			}
		}		
		return ans;
	}

四、像用哈希但是其实哈希不合适

15. 三数之和

这题不适合用哈希。

两层for循环就可以确定 a 和b 的数值了,可以使用哈希法来确定 0-(a+b) 是否在 数组里出现过,其实这个思路是正确的,但是我们有一个非常棘手的问题,就是题目中说的不可以包含重复的三元组。

把符合条件的三元组放进vector中,然后再去重,这样是非常费时的,很容易超时,也是这道题目通过率如此之低的根源所在。

去重的过程不好处理,有很多小细节,如果在面试中很难想到位。

排序+双指针

	public List<List<Integer>> threeSum(int[] nums) {
		List<List<Integer>> ans = new ArrayList<>();
        Arrays.sort(nums);
        
        for(int i=0; i<nums.length; i++){
        	if (nums[i] > 0) return ans;//如果一开始就大于0,后面肯定没有正确答案
        	if (i > 0 && nums[i] == nums[i - 1]) continue;//如果和刚才一样,没必要重算
        	
        	int l = i+1;
        	int r = nums.length-1;
        	while(l<r){
        		int tosum = nums[i] + nums[l] + nums[r];
        		if(tosum == 0){//如果当前三个数和为0
        			List<Integer> newans = new ArrayList<Integer>();
        			newans.add(nums[i]);
        			newans.add(nums[l]);
        			newans.add(nums[r]);
        			ans.add(newans);
        			//直到左右没有重复的数字为止
        			while (r > l && nums[r] == nums[r - 1]) r--;
                    while (r > l && nums[l] == nums[l + 1]) l++;
                    //因为当前已经满足和为0了,所以必须左右同时减,只有一边动的话肯定不满足
                    r--; 
                    l++;
        		}else if(tosum < 0){
        			l++;
        		}else{
        			r--;
        		}
        	}       	
        }       
        return ans;
	}

18. 四数之和

https://leetcode-cn.com/problems/4sum/
和三数之和一个逻辑,多一层for循环

public List<List<Integer>> fourSum(int[] nums, int target) {
        List<List<Integer>> result = new ArrayList<>();
        Arrays.sort(nums);
       
        for (int i = 0; i < nums.length; i++) {

            if (i > 0 && nums[i - 1] == nums[i]) {
                continue;
            }
            
            for (int j = i + 1; j < nums.length; j++) {

                if (j > i + 1 && nums[j - 1] == nums[j]) {
                    continue;
                }

                int left = j + 1;
                int right = nums.length - 1;
                while (right > left) {
                    int sum = nums[i] + nums[j] + nums[left] + nums[right];
                    if (sum > target) {
                        right--;
                    } else if (sum < target) {
                        left++;
                    } else {
                        result.add(Arrays.asList(nums[i], nums[j], nums[left], nums[right]));
                        
                        while (right > left && nums[right] == nums[right - 1]) right--;
                        while (right > left && nums[left] == nums[left + 1]) left++;

                        left++;
                        right--;
                    }
                }
            }
        }
        return result;
    }
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-03-10 22:50:47  更:2022-03-10 22:55:43 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 13:27:17-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码