java 字符串距离计算 牛客网 (入门算法与高效算法)

题目描述
给定两个长度相等的,由小写字母组成的字符串S1和S2,定义S1和S2的距离为两个字符串有多少个位置上的字母不相等。
现在牛牛可以选定两个字母X1和X2,将S1中的所有字母X1均替换成X2。(X1和X2可以相同)
牛牛希望知道执行一次替换之后,两个字符串的距离最少为多少。

题目链接:hey look at me babe

题目理解:两个一样长的字符串S1、S2。
>>每出现一次对应位置不等的情况距离+1<<
全部对应相等距离 = 0,全部对应不等距离等于S1.length
可以把S1里的某个字符换成S2里的某个字符,来达到使距离最少的情况。

那如何替换会达到我们想要的效果呢?

如果不考虑对应位置这一因素。我们只需要找到S1中不匹配并且出现次数最多的字符把他替换成S2中不匹配并且出现次数最多的字符。这样就可以达到我们的目的。但是我们需要考虑对应位置的情况。

为了解决这一问题。我们可以使用HashMap来记录不匹配对。比如"abcd" "efgh"我们在hashMap中以ae bf cg dh作为key保存。如果不匹配的字符对多次出现,那么则对应key值加一。我们需要找到key值最大的不匹配对。用原距离减去最大不匹配对就可以得到我们想要的结果了。

但是我们忽略了一个问题:如果字符串是这样的"aaabcd" “aeefgh”。在字符串中有一对aa是对应的。如果我们把ae对中的a全部修改为e那么原来匹配的aa就变成了ea。我们需要考虑到修改字符对已匹配的字符会产生多大的影响。
为了解决这一问题,我们还需要一个HashMap去存储匹配的字符以及匹配的数量。在我们检索不匹配对寻找可以最大减少距离的不匹配对时应该去考虑修改不匹配对。对已匹配对产生的影响。

这样我们就可以解出这道题目。


```java
import java.util.*;


public class Solution {
    /**
     * 计算最少的距离
     * @param S1 string字符串 第一个字符串
     * @param S2 string字符串 第二个字符串
     * @return int整型
     */
    public int GetMinDistance (String S1, String S2) {
        // write code here
        HashMap<String ,Integer> map1 = new HashMap<String, Integer>();
        HashMap<Character ,Integer> map2 = new HashMap<Character, Integer>();
        char[] ch1 = S1.toCharArray();
        char[] ch2 = S2.toCharArray();
        int count = 0;
        for (int i = 0; i < ch1.length; i++) {
            if(ch1[i] != ch2[i]) {
                StringBuilder sb = new StringBuilder();
                sb.append(ch1[i]).append(ch2[i]);
                String str = new String(sb);
                map1.put(str,map1.containsKey(str) ? map1.get(str) + 1 : 1);
                count++;
            }else {
                map2.put(ch1[i],map2.containsKey(ch1[i]) ? map2.get(ch1[i]) + 1 : 1);  
            }
        }
        return count - findMax(map1,map2);
    }

    private int findMax(HashMap<String,Integer> map1, HashMap<Character,Integer> map2) {
        Set<String> set = map1.keySet();
        int max = Integer.MIN_VALUE;
        for (String s : set) {
            if(map2.containsKey(s.charAt(0))) {
                if(max < map1.get(s) - map2.get(s.charAt(0))) {
                    max = map1.get(s) - map2.get(s.charAt(0));
                }
            }else {
                max = max > map1.get(s) ? max : map1.get(s);
            }
        }
        return max;
    }
}

大家应该注意到我题目里写的是入门算法与高效算法。更高效的算法是我在牛客排行榜上看到的。
其实思路是换汤不换药的。只是在存储上容器,他选择了更加高效的二维数组在存储。
因为字符串中都是小写字母。我们只需要执行:(int) 字符 - ‘a’。就可以将字母与数组下标建立对应的联系。
举例:aa 出现次数就是00下标中的数字。ab出现次数就是01下标中的数字。

剩下的思路是一样的就不再赘述。

上代码:


```java
import java.util.*;
 
 
public class Solution {
    /**
     * 计算最少的距离
     * @param S1 string字符串 第一个字符串
     * @param S2 string字符串 第二个字符串
     * @return int整型
     */
    public int GetMinDistance (String S1, String S2) {
        // write code here
         int[][] count = new int[26][26];  //count[i][j] means same location
        //s1 char is i and s2 char is j
        int n = S1.length();
        int diff = 0;
        for (int i = 0; i < n; ++i) {
            int a = S1.charAt(i) - 'a', b = S2.charAt(i) - 'a';
            ++count[a][b];
            diff += a != b ? 1 : 0;
        }
        int ans = Integer.MAX_VALUE;
        for (int i = 0; i < 26; ++i) {
            for (int j = 0; j < 26; ++j) {
                //change all i to j in s1
                ans = Math.min(ans, diff + count[i][i] - count[i][j]);
            }
        }
        return ans;
    }
}

如果帮到了你,请点个赞鼓励一下我吧。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值