首页 > 编程语言 >算法解析-经典150(矩阵、哈希表)

算法解析-经典150(矩阵、哈希表)

时间:2025-01-03 22:30:51浏览次数:3  
标签:150 return map int 矩阵 ++ length 哈希 public

文章目录

矩阵

1.有效的数独

1.答案
package com.sunxiansheng.classic150.g1;

/**
 * Description: 36. 有效的数独
 *
 * @Author sun
 * @Create 2024/12/22 10:02
 * @Version 1.0
 */
public class t36 {

    public boolean isValidSudoku(char[][] board) {
        boolean[][] rows = new boolean[9][9];
        boolean[][] cols = new boolean[9][9];
        boolean[][] boxes = new boolean[9][9];
        int m = board.length;
        int n = board[0].length;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                // 获取元素
                char c = board[i][j];
                // 跳过空格
                if (c == '.') {
                    continue;
                }
                // 转换为索引,方便存入数组
                int index = c - '1';
                // 放入当前行
                if (rows[i][index]) {
                    return false;
                } else {
                    rows[i][index] = true;
                }
                // 放入当前列
                if (cols[index][j]) {
                    return false;
                } else {
                    cols[index][j] = true;
                }
                // 计算3x3子宫格的索引
                int boxIndex = (i / 3) * 3 + j / 3;
                if (boxes[boxIndex][index]) {
                    return false;
                } else {
                    boxes[boxIndex][index] = true;
                }
            }
        }
        return true;
    }
}
2.思路

记住这个公式:int boxIndex = (i / 3) * 3 + j / 3;

2.螺旋矩阵

1.答案
package com.sunxiansheng.classic150.g1;

import java.util.ArrayList;
import java.util.List;

/**
 * Description: 54. 螺旋矩阵
 *
 * @Author sun
 * @Create 2024/12/22 10:43
 * @Version 1.0
 */
public class t54 {

    public static List<Integer> spiralOrder(int[][] matrix) {
        List<Integer> res = new ArrayList<>();
        int m = matrix.length;
        int n = matrix[0].length;
        // 定义上下左右边界
        int top = 0;
        int bottom = m - 1;
        int left = 0;
        int right = n - 1;
        // 计算一共需要遍历的次数
        int total = m * n;
        int count = 0;
        // 按照右下左上的顺序遍历
        while (true) {
            // 右
            for (int i = left; i <= right; i++) {
                res.add(matrix[top][i]);
                if (++count == total) {
                    return res;
                }
            }
            // 上边界下移
            top++;
            // 下
            for (int i = top; i <= bottom; i++) {
                res.add(matrix[i][right]);
                if (++count == total) {
                    return res;
                }
            }
            // 右边界左移
            right--;
            // 左
            for (int i = right; i >= left; i--){
                res.add(matrix[bottom][i]);
                if (++count == total) {
                    return res;
                }
            }
            // 下边界上移
            bottom--;
            // 上
            for (int i = bottom; i >= top; i--) {
                res.add(matrix[i][left]);
                if (++count == total) {
                    return res;
                }
            }
            // 左边界右移
            left++;
        }
    }
}
2.思路

先定义四个边界,然后记录一共需要遍历的次数,最后在循环内按照顺序遍历,每次遍历完成都要移动边界

3.旋转图像

1.答案
package com.sunxiansheng.classic150.g1;

/**
 * Description: 48. 旋转图像
 *
 * @Author sun
 * @Create 2024/12/22 11:11
 * @Version 1.0
 */
public class t48 {

    public static void rotate(int[][] matrix) {
        // 矩阵转置
        int n = matrix.length;
        for (int i = 0; i < n; i++) {
            for (int j = i; j < n; j++) {
                int temp = matrix[i][j];
                matrix[i][j] = matrix[j][i];
                matrix[j][i] = temp;
            }
        }
        // 将每一行都逆序
        for (int i = 0; i < matrix.length; i++) {
            reverse(matrix[i]);
        }
    }

    /**
     * 逆序数组
     *
     * @param arr
     */
    private static void reverse(int[] arr) {
        int left = 0;
        int right = arr.length - 1;
        while (left < right) {
            int temp = arr[left];
            arr[left] = arr[right];
            arr[right] = temp;
            left++;
            right--;
        }
    }
}
2.思路

转置后逆序即可

4.矩阵置零

1.答案
package com.sunxiansheng.classic150.g1;

import javafx.util.Pair;

import java.util.ArrayList;
import java.util.List;

/**
 * Description: 73. 矩阵置零
 *
 * @Author sun
 * @Create 2024/12/22 11:20
 * @Version 1.0
 */
public class t73 {

    public static void setZeroes(int[][] matrix) {
        // 记录一下需要置0的下标
        List<Pair<Integer, Integer>> list = new ArrayList<>();
        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[0].length; j++) {
                if (matrix[i][j] == 0) {
                    list.add(new Pair<>(i, j));
                }
            }
        }
        // 设置0
        for (int i = 0; i < list.size(); i++) {
            setZero(matrix, list.get(i).getKey(), list.get(i).getValue());
        }
    }

    private static void setZero(int[][] matrix, int row, int col) {
        int top = 0;
        int bottom = matrix.length - 1;
        int left = 0;
        int right = matrix[0].length - 1;
        // 向上置0
        for (int i = row; i >= top; i--) {
            matrix[i][col] = 0;
        }
        // 向下
        for (int i = row; i <= bottom; i++) {
            matrix[i][col] = 0;
        }
        // 向左
        for (int i = left; i <= col; i++) {
            matrix[row][i] = 0;
        }
        // 向右
        for (int i = right; i >= col; i--) {
            matrix[row][i] = 0;
        }
    }
}
2.思路

先要记录一下要置0的下标,然后遍历去置0即可

哈希表

1.赎金信

1.答案
package com.sunxiansheng.classic150.g1;

/**
 * Description: 383. 赎金信
 *
 * @Author sun
 * @Create 2024/12/22 13:27
 * @Version 1.0
 */
public class t383 {

    public static boolean canConstruct(String ransomNote, String magazine) {
        // 统计字符频率
        int[] mFreq = new int[26];
        for (int i = 0; i < magazine.length(); i++) {
            mFreq[magazine.charAt(i) - 'a'] ++;
        }
        // 遍历ransomNote看看够不够减
        for (int i = 0; i < ransomNote.length(); i++) {
            // 计算下标
            int index = ransomNote.charAt(i) - 'a';
            if (--mFreq[index] < 0) {
                return false;
            }
        }
        return true;
    }
}
2.思路

先统计一下字符的频率,然后看看够不够减就可以

2.同构字符串

1.答案
package com.sunxiansheng.classic150.g1;

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

/**
 * Description: 205. 同构字符串
 *
 * @Author sun
 * @Create 2024/12/22 13:44
 * @Version 1.0
 */
public class t205 {

    public boolean isIsomorphic(String s, String t) {
        if (s.length() != t.length()) {
            return false;
        }
        // 双向映射:s -> t 和 t -> s
        Map<Character, Character> mapS2T = new HashMap<>();
        Map<Character, Character> mapT2S = new HashMap<>();
        for (int i = 0; i < s.length(); i++) {
            // 获取元素
            char charS = s.charAt(i);
            char charT = t.charAt(i);
            // 检查s到t是否有映射
            if (mapS2T.containsKey(charS)) {
                // 有映射就检查当前映射
                if (mapS2T.get(charS) != charT) {
                    return false;
                }
            } else {
                // 没有映射就建立映射
                mapS2T.put(charS, charT);
            }
            // 检查t到s是否有映射
            if (mapT2S.containsKey(charT)) {
                // 有映射就检查当前映射
                if (mapT2S.get(charT) != charS) {
                    return false;
                }
            } else {
                // 没有映射就建立映射
                mapT2S.put(charT, charS);
            }
        }
        return true;
    }
}
2.思路

就是检查双向映射,具体检查的过程就是:先判断有没有映射,如果有则检查,没有就建立映射

3.单词规律

1.答案
package com.sunxiansheng.classic150.g1;

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

/**
 * Description: 290. 单词规律
 *
 * @Author sun
 * @Create 2024/12/22 14:06
 * @Version 1.0
 */
public class t290 {

    public static boolean wordPattern(String pattern, String s) {
        // s以空格分割
        String[] split = s.split(" ");
        if (split.length != pattern.length()) {
            return false;
        }
        // 双向映射
        Map<Character, String> map = new HashMap<>();
        Map<String, Character> map2 = new HashMap<>();
        for (int i = 0; i < pattern.length(); i++) {
            // 取数
            char left = pattern.charAt(i);
            String right = split[i];
            // 检查是否有映射
            if (map.containsKey(left)) {
                // 如果有,则检查映射
                if (!map.get(left).equals(right)) {
                    return false;
                }
            } else {
                // 如果没有,就添加映射
                map.put(left, right);
            }

            // 检查是否有映射
            if (map2.containsKey(right)) {
                // 如果有,则检查映射
                if (!map2.get(right).equals(left)) {
                    return false;
                }
            } else {
                // 如果没有,就添加映射
                map2.put(right, left);
            }

        }
        return true;
    }
}
2.思路

也是一个双向映射

4.有效的字母异位词

1.答案
package com.sunxiansheng.classic150.g1;

import java.util.Arrays;

/**
 * Description: 242. 有效的字母异位词
 *
 * @Author sun
 * @Create 2024/12/22 14:22
 * @Version 1.0
 */
public class t242 {

    public static boolean isAnagram(String s, String t) {
        // 计算频率,看频率是否相同
        int[] sFeq = new int[26];
        int[] tFeq = new int[26];

        for (int i = 0; i < s.length(); i++) {
            sFeq[s.charAt(i) - 'a']++;
        }
        for (int j = 0; j < t.length(); j++) {
            tFeq[t.charAt(j) - 'a']++;
        }

        return Arrays.equals(sFeq, tFeq);
    }
}
2.思路

就是转化为频率数组,判断两个数组是不是一样就可以

5.字母异位词分组

1.答案
package com.sunxiansheng.classic150.g1;

import java.util.*;

/**
 * Description: 49. 字母异位词分组
 *
 * @Author sun
 * @Create 2024/12/22 14:29
 * @Version 1.0
 */
public class t49 {

    public static List<List<String>> groupAnagrams(String[] strs) {
        List<List<String>> res = new ArrayList<>();
        if (strs == null || strs.length == 0) {
            return res;
        }
        // 存储结果的map
        Map<String, List<String>> map = new HashMap<>();
        for (int i = 0; i < strs.length; i++) {
            char[] charArray = strs[i].toCharArray();
            // 排序
            Arrays.sort(charArray);
            // 转换为String
            String key = String.valueOf(charArray);
            // 判断map中是否有相同的
            List<String> list = null;
            if (map.containsKey(key)) {
                list = map.get(key);
            } else {
                list = new ArrayList<>();
            }
            list.add(strs[i]);
            map.put(key, list);
        }
        return new ArrayList<>(map.values());
    }
}
2.思路

就是使用一个map,其中的key是排序后的字符串,value就是与排序后的字符串相同的元素,遍历去比较即可

6.两数之和

1.答案
package com.sunxiansheng.classic150.g1;

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

/**
 * Description: 1. 两数之和
 *
 * @Author sun
 * @Create 2024/12/22 14:52
 * @Version 1.0
 */
public class t1 {

    public static int[] twoSum(int[] nums, int target) {
        // 哈希表来记录
        Map<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < nums.length; i++) {
            // 计算差
            int diff = target - nums[i];
            // 如果map中有这个差值对应的就返回结果
            if (map.containsKey(diff)) {
                return new int[]{i, map.get(diff)};
            }
            // 如果没有,就把自己放到map中
            map.put(nums[i], i);
        }
        return null;
    }
}
2.思路

就是使用哈希表来记录元素以及元素下标,然后遍历的时候先判断哈希表中有没有目标元素减去当前元素的差,如果有就直接返回,没有就将当前元素放到map中

7.快乐数

1.答案
package com.sunxiansheng.classic150.g1;

import java.util.HashSet;
import java.util.Set;

/**
 * Description: 202. 快乐数
 *
 * @Author sun
 * @Create 2024/12/22 15:20
 * @Version 1.0
 */
public class t202 {

    public static boolean isHappy(int n) {
        // 使用集合来记录结果,也可以判断是否重复
        Set<Integer> set = new HashSet<>();
        while (n != 1) {
            int num = getNum(n);
            // 只要set中出现了num那么就是重复了直接返回false
            if (set.contains(num)) {
                return false;
            }
            set.add(num);
            n = num;
        }
        return true;
    }

    /**
     * 获取这个数每个位置的平方和
     *
     * @return
     */
    private static int getNum(int num) {
        int res = 0;
        while (num > 0) {
            int cur = num % 10;
            res += cur * cur;
            num /= 10;
        }
        return res;
    }

    public static void main(String[] args) {
        isHappy(19);
    }
}
2.思路

使用set来记录计算后的结果,核心就是在加入之前先判断set中是否已经有这个结果了,如果有,就是开始重复了,表明不是快乐数

8.存在重复元素 II

1.答案
package com.sunxiansheng.classic150.g1;

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

/**
 * Description: 219. 存在重复元素 II
 *
 * @Author sun
 * @Create 2024/12/22 15:36
 * @Version 1.0
 */
public class t219 {

    public static boolean containsNearbyDuplicate(int[] nums, int k) {
        // map存储
        Map<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < nums.length; i++) {
            // 如果map中有
            if (map.containsKey(nums[i])) {
                // 进一步判断是否满足要求
                if (Math.abs(map.get(nums[i]) - i) <= k) {
                    // 如果满足要求就直接返回
                    return true;
                }
                // 不满足要求就更新map
                map.put(nums[i], i);
            } else {
                // 没有就添加到map中
                map.put(nums[i], i);
            }
        }
        return false;
    }

    public static void main(String[] args) {
        System.out.println("containsNearbyDuplicate(new int[]{1,0,1,1}, 1) = " + containsNearbyDuplicate(new int[]{1, 0, 1, 1}, 1));
    }
}
2.思路

使用map来存储元素和下标,先判断map中有没有与当前元素相同的元素,如果没有就加入到map,如果有,就进一步判断是否能满足要求,如果满足就返回结果,如果不满足就更新map

9.最长连续序列

1.答案
package com.sunxiansheng.classic150.g1;

import java.util.Arrays;

/**
 * Description: 128. 最长连续序列
 *
 * @Author sun
 * @Create 2024/12/23 12:52
 * @Version 1.0
 */
public class t128 {

    public static int longestConsecutive(int[] nums) {
        if (nums == null || nums.length == 0) {
            return 0;
        }
        int res = 1;
        // 1 2 3 3 4 100 200
        Arrays.sort(nums);
        // dp[i]:以i结尾的最长连续序列的长度
        // 状态转移:当nums[i] == nums[i - 1] + 1 dp[i] = dp[i - 1] + 1
        // 当nums[i] == nums[i - 1] dp[i] = dp[i - 1]
        // 当nums[i] > nums[i - 1] + 1 dp[i] = 1
        // 初始化
        int[] dp = new int[nums.length];
        dp[0] = 1;
        for (int i = 1; i < dp.length; i++) {
            dp[i] = 1;
            if (nums[i] == nums[i - 1] + 1) {
                dp[i] = dp[i - 1] + 1;
            } else if (nums[i] == nums[i - 1]) {
                dp[i] = dp[i - 1];
            } else {
                dp[i] = 1;
            }
            res = Math.max(res, dp[i]);
        }
        return res;
    }

    public static void main(String[] args) {
        System.out.println("longestConsecutive(new int[]{1,2,3,3,4,100,200}) = " + longestConsecutive(new int[]{1, 2, 3, 3, 4, 100, 200}));
    }
}
2.思路

首先对数组排序,然后使用动态规划,定义为dp[i]:以i结尾的最长连续序列的长度,分为三种情况,第一种是当前元素等于前一个元素加一,那么dp[i] = dp[i - 1] + 1,第二种是当前元素跟前一个元素相同,dp[i] = dp[i - 1] 最后一种情况就是当前元素比前一个元素加一还要大,就说明不是连续的,所以当前元素结尾的最长连续序列的长度就是1

标签:150,return,map,int,矩阵,++,length,哈希,public
From: https://blog.csdn.net/m0_64637029/article/details/144919249

相关文章

  • 『矩阵树定理,LGV引理,行列式』Day9 略解
    前言我抓不住世间的美好,所以只能装作万事顺遂的模样第二个链接,做是做不起一点的,只能乞讨别考这些**东西。A最小带权生成树计数板题。(其实没这么多戏份)首先先求出任意一颗最小生成树,如果没有直接输出\(0\)。对于生成树上的每一种边权分别出来,每次把当前边权在原图上所有的......
  • 『联合省选2025集训』『矩阵树定理,LGV引理,行列式』 Day8 略解
    前言许多人所谓的成熟,不过是被习俗磨去了棱角,变得世故而实际了。这两天的线性代数属实是要给我创破防了。拼尽全力战胜基础题目之后,难的题目偏的偏怪的怪,还有一堆不会的数学知识点,我还是摆烂了吧。先稍做一下总结。以及,我突然意识到总结的效率问题,或许我真的应该减少每道题......
  • 机器学习之模型评估——混淆矩阵,交叉验证与数据标准化
    目录混淆矩阵交叉验证数据标准化        0-1标准化        z标准化混淆矩阵混淆矩阵(ConfusionMatrix)是一种用于评估分类模型性能的工具。它是一个二维表格,其中行表示实际的类别,列表示模型预测的类别。假设我们有一个二分类问题(类别为正例和反例),......
  • 哈希算法篇——散落的秘密与精准的归宿,混沌中的秩序之美(上)
    文章目录引言:混沌中的秩序之美第一章:哈希的本质——化繁为简的魔法第二章:经典哈希函数——一座算法的博物馆第三章:哈希表的奇迹——从无序到有序的转变3.1哈希函数的基本实现3.2基本的哈希表实现3.3哈希算法的实际应用小结引言:混沌中的秩序之美在信息科学的星......
  • 矩阵
    矩阵矩阵的秩概述矩阵的秩是线性代数中的一个基本概念,它描述了矩阵中行向量或列向量的最大线性无关组的个数。即行向量或列向量的线性基。使用\(\text{rank}(A)\)表示矩阵\(A\)的秩。性质矩阵的转置不改变其秩,即\(\text{rank}(A)=\text{rank}(A^T)\)。矩阵的......
  • 社媒运营必学装X技能,五分钟搞定whatsapp矩阵部署跨境
    五分钟搞定whatsapp矩阵部署,跨境社媒运营必学装X技能引言在全球化的商业环境中,社交媒体运营已经成为企业拓展国际市场的重要手段。WhatsApp作为全球最受欢迎的即时通讯工具之一,其在全球拥有超过20亿的月活跃用户,是跨境社媒运营不可忽视的平台。本文将带你快速掌握WhatsApp矩......
  • 打造三甲医院人工智能矩阵新引擎:文本大模型篇--基于GPT-4o的探索(一)
    一、引言当今时代,人工智能技术正以前所未有的速度蓬勃发展,深刻且广泛地渗透至各个领域,医疗行业更是这场变革的前沿阵地。在人口老龄化加剧、慢性疾病患病率上升以及人们对健康需求日益增长的大背景下,三甲医院作为医疗体系的核心力量,承担着极为繁重且复杂的医疗任务。传统医......
  • 20章4节:绘制高级散点矩阵图和多样生存曲线图
    在高维数据探索中,散点矩阵图和生存曲线图作为经典的可视化方法,广泛应用于医疗、社会科学以及生物统计学领域。散点矩阵图可以高效地呈现多变量之间的相互关系,帮助研究人员快速发现潜在的模式或异常;而生存曲线图则通过展示随时间变化的生存概率,直观地表现出事件发生的时间分布......
  • 线性代数5.矩阵的行列式-相关性质
    5.矩阵的行列式-相关性质若存在行列式:\[|A|=\begin{vmatrix}a_{11}&a_{12}&a_{13}&...&a_{1n}\\a_{21}&a_{22}&a_{23}&...&a_{2n}\\a_{31}&a_{32}&a_{33}&...&a_{3n}\\&&......\\a_{n1}&......
  • Luogu P9646 SNCPC2019 Paper-cutting 题解 [ 紫 ] [ manacher ] [ 贪心 ] [ 哈希 ] [
    Paper-cutting:思维很好,但代码很构式的manacher题。蒟蒻2025年切的第一道题,是个紫,并且基本独立想出的,特此纪念。判断能否折叠我们先考虑一部分能折叠需要满足什么条件。显然,这一部分需要是一个长度为偶数的回文串。那么横向和纵向会不会影响呢?答案是不会,因为横向折了之后,折......