刷题_23:微信红包 and 计算字符串的编辑距离

文章介绍了如何使用高效算法解决两个编程问题:一是找出在红包金额数组中出现次数超过一半的金额,二是计算两个字符串之间的编辑距离。提供的解决方案分别涉及单遍历法和动态规划,均具有较好的时间复杂度和空间复杂度。
摘要由CSDN通过智能技术生成

一.微信红包

题目链接:

微信红包

题目描述:

春节期间小明使用微信收到很多个红包,非常开心。在查看领取红包记录时发现,某个红包金额出现的次数超过了红包总数的一半。请帮小明找到该红包金额。写出具体算法思路和代码实现,要求算法尽可能高效。
给定一个红包的金额数组 gifts 及它的大小 n ,请返回所求红包的金额。
若没有金额超过总数的一半,返回0。
数据范围: 1≤n≤1000 ,红包金额满足 1≤gifti ≤100000

输入描述:

输出描述:

示例1:

输入:
[1,2,3,2,2],5
输出:
2

示例2:

输入:
[1,1,2,2,3,3],6
输出:
0

个人总结:

时间复杂度O(n),空间复杂度O(1)。注意他题干说的是红包金额出现的次数超过了红包总数的一半,而不是金额总数,此题哈希表也能写,这个方法也行,用这个方法的话参数n压根没用到,和我之前见的一个题目比较类似,详细请走 多数元素

代码实现:

import java.util.*;

public class Gift {
    public int getValue(int[] gifts, int n) {
        // write code here
        //记录金额
        int res = 0;
        //记录出现次数
        int cnt = 0;
        for (int i = 0; i < gifts.length; i++) {
            if (res == gifts[i]) {
                cnt++;
            } else {
                cnt--;
                if (cnt < 0) {
                    res = gifts[i];
                    cnt = 0;
                }
            }
        }
        return cnt == 0 ? 0 : res;
    }
}

二.计算字符串的编辑距离

题目链接:

计算字符串的编辑距离

题目描述:

Levenshtein 距离,又称编辑距离,指的是两个字符串之间,由一个转换成另一个所需的最少编辑操作次数。许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。编辑距离的算法是首先由俄国科学家 Levenshtein 提出的,故又叫 Levenshtein Distance 。
例如:
字符串A: abcdefg
字符串B: abcdef
通过增加或是删掉字符 ”g” 的方式达到目的。这两种方案都需要一次操作。把这个操作所需要的次数定义为两个字符串的距离。
要求:
给定任意两个字符串,写出一个算法计算它们的编辑距离。
数据范围:给定的字符串长度满足 1≤len(str)≤1000

输入描述:

每组用例一共2行,为输入的两个字符串

输出描述:

每组用例输出一行,代表字符串的距离

示例1:

输入:
abcdefg
abcdef
输出:
1

个人总结:

动态规划题,我们对字符串的编辑操作可以分为:替换、增加、删除三个操作,虽然增加和删除是一个互逆的操作,可以简化转移方程,但是!我忘了怎么搞了,所以我们还是全部考虑吧。我们来分析一下两层for循环内部的代码:
定义一下,方便叙述:s[i - 1]意思是 0 ~ i - 1的s子串。
if (s.charAt(i - 1) == p.charAt(j - 1)) :则dp[i][j] = dp[i - 1][j - 1];,意思是如果字符相等可以匹配,则最少的编辑次数等于s[i - 1]和p[j - 1]的最少编辑次数,即本次不需要编辑,次数和上次一样。
if (s.charAt(i - 1) != p.charAt(j - 1)) :则取dp[i - 1][j - 1]dp[i - 1][j]dp[i][j - 1]的最小值然后加1(进行了一次编辑)。
dp[i - 1][j - 1] + 1:执行一次替换操作,则最少的编辑次数等于s[i - 1]和p[j - 1]的最少编辑次数 + 一次替换。
dp[i - 1][j] + 1:对p执行一次增加操作,则s.charAt(i - 1)和 p.charAt(j - 2)匹配,所以最少的编辑次数等于s[i - 1]和p[j - 2]的最少编辑次数 + 一次增加。
dp[i][j - 1] + 1:对p执行一次删除操作,则s.charAt(i - 2)和 p.charAt(j - 1)匹配,所以最少的编辑次数等于s[i - 2]和p[j - 1]的最少编辑次数 + 一次删除。

代码实现:

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String s = sc.nextLine();
        String p = sc.nextLine();
        System.out.println(getMinLevenshtein(s, p));
    }
    
    public static int getMinLevenshtein(String s, String p) {
        int lenS = s.length();
        int lenP = p.length();
        //dp[i][j]:长度为i的s编辑成长度为j的p的最少操作次数
        int[][] dp = new int[lenS + 1][lenP + 1];
        for (int i = 1; i <= lenS; i++) {
            dp[i][0] = i;
        }
        for (int j = 1; j <= lenP; j++) {
            dp[0][j] = j;
        }
        for (int i = 1; i <= lenS; i++) {
            for (int j = 1; j <= lenP; j++) {
                if (s.charAt(i - 1) == p.charAt(j - 1)) {
                    dp[i][j] = dp[i - 1][j - 1];
                } else {
                    dp[i][j] = Math.min(dp[i - 1][j - 1], Math.min(dp[i - 1][j], dp[i][j - 1])) + 1;
                }
            }
        }
        return dp[lenS][lenP];
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

木木是木木

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值