ecs初体验-算法

本文涉及的产品
云服务器 ECS,每月免费额度200元 3个月
云服务器ECS,u1 2核4GB 1个月
简介: ecs初体验-算法

nSum 问题

如果假设输入一个数组 nums 和一个目标和 target,请你返回 nums 中能够凑出 target 的两个元素的值,比如输入 nums = [1,3,5,6], target = 9,那么算法返回两个元素 [3,6]

Java版nSum模板及4Sum调用示例:

public List<List<Integer>> fourSum(int[] nums, int target) {
        // 排序
        Arrays.sort(nums);
        
        return nSum(nums, 4, 0, target);
    }
// parameter1: 数组 parameter2: n parameter3: 数组中的起始位置 parameter4: 当前的目标 
private List<List<Integer>> nSum(int[] nums, int n, int start, int target) {
    int len = nums.length;
    // 存放结果的list
    List<List<Integer>> res = new ArrayList<List<Integer>>();
    if (n < 2 || len < n)
        return res;
    // 当n == 2 时,最基本的双指针
    if (n == 2) {
        int small = start, big = len - 1;
        while (small < big) {
            int left = nums[small], right = nums[big];
            int sum = left + right;
            // 总和等于目标时, 
            if (sum == target) {
                // 结果list添加新的值
                res.add(new ArrayList<Integer>(Arrays.asList(left, right)));
                // 去掉左边重复的元素
                while (small < big && nums[small] == left)
                    small++;
                // 去掉右边重复的元素
                while (small < big && nums[big] == right)
                    big--;
            } else if (sum > target) {
                // 右指针向左移动 并去掉右边重复的元素
                while (small < big && nums[big] == right)
                    big--;
            } else if (sum < target) {
                // 左指针向右移动 并去掉左边重复的元素
                while (small < big && nums[small] == left)
                    small++;
            }
        }
    } else {
        // 当n != 2 时 准备进行递归调用
        int i = start;
        // 对start之后的每一个元素递归
        while (i < len) {
            int now = nums[i];
            List<List<Integer>> sub = nSum(nums, n - 1, i + 1, target - now);
            // 把当前值和递归结果合并,并加到res中
            for (List<Integer> s : sub) {
                s.add(now);
                res.add(s);
            }
            // 对当前值进行去重
            while (i < len && nums[i] == now)
                i++;
        }
    }
    return res;
}

字符串匹配

Rabin-Karp 算法

利用滑动窗口,将窗口内中的字符串匹配成数字(哈希)

// Rabin-Karp 指纹字符串查找算法
int rabinKarp(String txt, String pat) {
    // 位数
    int L = pat.length();
    // 进制(只考虑 ASCII 编码)
    int R = 256;
    // 取一个比较大的素数作为求模的除数
    long Q = 1658598167;
    // R^(L - 1) 的结果
    long RL = 1;
    for (int i = 1; i <= L - 1; i++) {
        // 计算过程中不断求模,避免溢出
        RL = (RL * R) % Q;
    }
    // 计算模式串的哈希值,时间 O(L)
    long patHash = 0;
    for (int i = 0; i < pat.length(); i++) {
        patHash = (R * patHash + pat.charAt(i)) % Q;
    }
    
    // 滑动窗口中子字符串的哈希值
    long windowHash = 0;
    
    // 滑动窗口代码框架,时间 O(N)
    int left = 0, right = 0;
    while (right < txt.length()) {
        // 扩大窗口,移入字符
        windowHash = ((R * windowHash) % Q + txt.charAt(right)) % Q;
        right++;

        // 当子串的长度达到要求
        if (right - left == L) {
            // 根据哈希值判断是否匹配模式串
            if (windowHash == patHash) {
                // 当前窗口中的子串哈希值等于模式串的哈希值
                // 还需进一步确认窗口子串是否真的和模式串相同,避免哈希冲突
                if (pat.equals(txt.substring(left, right))) {
                    return left;
                }
            }
            // 缩小窗口,移出字符
            windowHash = (windowHash - (txt.charAt(left) * RL) % Q + Q) % Q;
            // X % Q == (X + Q) % Q 是一个模运算法则
            // 因为 windowHash - (txt[left] * RL) % Q 可能是负数
            // 所以额外再加一个 Q,保证 windowHash 不会是负数

            left++;
        }
    }
    // 没有找到模式串
    return -1;
}

KMP 算法

  1. 每次匹配不成功时,应该回退到哪?(回退到影子状态的位置)(影子状态是与当前状态有相同的前缀的状态)
  2. 影子状态怎么确定?(前进或回退到影子状态下出现该字符的状态)
    // dp[j][c] 表示状态j下,出现字符c时,应该转移到的状态(只与pat有关)
    private int [][] dp;

    public int strStr(String txt, String pat) {
        kmp(pat);
        int M = pat.length(), N = txt.length();
        // 从状态0开始
        int j = 0;
        for(int i = 0; i < N; i++){
            // 状态的转移
            j = dp[j][txt.charAt(i)];
            // 当状态转移到最后,说明匹配成功
            if(j == M){
                // 返回初始下标
                return i - M + 1;
            }
        }
        return -1;
    }

    public void kmp(String pat){
        int M = pat.length();
        dp = new int [M][256];

        // base case 
        dp[0][pat.charAt(0)] = 1;

        // 定义影子状态,(与当前j状态有相同的前缀)
        int X = 0;
        // 状态从1开始
        for(int j = 1; j < M; j++){
            for(char c = 0; c < 256; c++){
                // 当与字符匹配时,状态向前移
                if(c == pat.charAt(j)){
                    dp[j][c] = j + 1;
                }
                // 否则回退到影子状态下出现字符c的状态
                else{
                    dp[j][c] = dp[X][c];
                }
            }
            // 更新影子状态(前进或回退到影子状态下出现该字符的状态)
            X = dp[X][pat.charAt(j)];
        }
    }

单调栈

输入一个数组 nums,请你返回一个等长的结果数组,结果数组中对应索引存储着下一个更大元素,如果没有更大的元素,就存 -1

输入数组[2,1,2,4,3] ------->结果数组[4,2,4,-1,-1]

int[] nextGreaterElement(int[] nums) {
    int n = nums.length;
    // 存放答案的数组
    int[] res = new int[n];
    Stack<Integer> s = new Stack<>(); 
    // 倒着往栈里放
    for (int i = n - 1; i >= 0; i--) {
        // 判定个子高矮
        // 单调栈的精髓
        while (!s.isEmpty() && s.peek() <= nums[i]) {
            // 矮个起开,反正也被挡着了。。。
            s.pop();
        }
        // nums[i] 身后的更大元素
        res[i] = s.isEmpty() ? -1 : s.peek();
        s.push(nums[i]);
    }
    return res;
}
相关实践学习
一小时快速掌握 SQL 语法
本实验带您学习SQL的基础语法,快速入门SQL。
7天玩转云服务器
云服务器ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,可降低 IT 成本,提升运维效率。本课程手把手带你了解ECS、掌握基本操作、动手实操快照管理、镜像管理等。了解产品详情:&nbsp;https://www.aliyun.com/product/ecs
相关文章
|
3天前
|
存储 弹性计算 算法
倚天产品介绍|倚天ECS加速国密算法性能
倚天ECS是阿里云基于平头哥自研数据中心芯片倚天710推出arm架构实例,采用armv9架构,支持SM3/SM4指令,可以加速国密算法性能。本文基于OpenSSL 3.2和Tongsuo 实测对比了倚天ECS g8y实例和Intel g7 实例国密性能。为用户选择ECS提供参考。
|
3天前
|
监控 负载均衡 网络协议
DNS服务器的搭建之初体验
通过这些步骤,你可以在初次搭建DNS服务器时获得基本的体验,了解如何为域名提供解析服务,促进网络的正常运行。 买CN2云服务器,免备案服务器,高防服务器,就选蓝易云。百度搜索:蓝易云
46 7
|
10月前
|
存储 弹性计算 算法
倚天ECS加速国密算法性能
倚天ECS是阿里云基于平头哥自研数据中心芯片倚天710推出arm架构实例,采用armv9架构,支持SM3/SM4指令,可以加速国密算法性能。本文基于OpenSSL 3.2和Tongsuo 实测对比了倚天ECS g8y实例和Intel g7 实例国密性能。为用户选择ECS提供参考。
|
机器学习/深度学习 弹性计算 Linux
大四计算机学生云服务器ESC初体验
本文是一位计算机科学与技术专业的大学生分享自己参加阿里云举办的高校学生在家实践活动的经历。该活动为学生提供了免费的算力平台,使学生能够更好地使用机器学习和数据处理工具。作者通过使用阿里云的ECS云服务器进行数据处理和机器学习模型的训练,发现其效率比个人电脑更高,对自己的研究和项目提供了很大的帮助。通过参加活动,作者深入了解了云服务器和机器学习的应用,并意识到其便利性和高效性。此外,作者也认为阿里云为高校学生提供免费算力服务的举措非常有帮助,可以让学生更好地掌握最新的技术和发展趋势,为未来的发展奠定更加坚实的基础。
|
SQL 弹性计算 数据库
飞天加速计划——ECS使用初体验
关于初次参与飞天加速计划以及初次使用阿里云ECS平台的体验。
|
算法 安全 网络安全
构建云服务器平台(jupter notebook)运行算法
构建云服务器平台(jupter notebook)运行算法的步骤
357 0
构建云服务器平台(jupter notebook)运行算法
|
存储 算法 安全
分布式服务器框架之Servers.Core库实现 DES对称加密算法;SHA1信息摘要算法;MD5信息摘要算法
通信双方(通信主体)同时掌握一个钥匙,加解密都由这一个钥匙完成。通信双方通信前共同拟定一个密钥,不向第三方公开,发送前加密和接受后解密都由此密钥完成。即钥匙如果泄露,将暴露自己的全部信息。
|
数据安全/隐私保护
分布式服务器框架之Server.Core库中实现 XXTEA分组加密算法
在密码学中,微型加密算法(Tiny Encryption Algorithm,TEA)是一种易于描述和执行的块密码,通常只需要很少的代码就可实现。其设计者是剑桥大学计算机实验室的大卫·惠勒与罗杰·尼达姆。这项技术最初于1994年提交给鲁汶的快速软件加密的研讨会上,并在该研讨会上演讲中首次发表。
|
弹性计算 物联网 数据安全/隐私保护
ECS之初体验
第一次使用ECS的体验,方便且好用。
186 0