判断两个字符串是否包含相同的字符(但是允许顺序不一样)

ABCC 在这里equals CBAC

先比较字符串长度就不说了

最笨拙的方法,遍历A字符串,然后再去遍历B字符串, 开一个新数组标记B上某位是否已匹配过。——O(n^2)

好一点的思路走向

字符串其实就是char数组,每一位的字符其实都是数字

所以“ABCC”是这样的

一个int数组。

不过我们不会真的转化成int数组,这样效率不高, 即取即用即可。

所以现在的任务变成了:确认两个int数组内包含的数字的种类和 个数是否相等。

这才是问题本来的样子

所以现在是排下序,排好序后一位位比过去吗?

这成本太大了。。。

所以我们需要统计每个数字出现的次数

然后大家比一下就好了

再具体 点呢?

65 66 67 67

67 66 65 67

第一行的属性

65 1

66 1

67 2

第二行的属性

65 1

66 1

67 2

我们是如何 收集数据的呢?

我们怎么知道他们是匹配的呢?

我一开始的想法是SparseArray,但是其保持增序的时候需要System.arrayCopy。用链表的话,查找又太过复杂

所以这里需要一张映射表

我们需要一个新的数组,可以覆盖到char 可能的每一个数字

然后下标代表了那个数,下标对应的值对应了那个数出现的次数。

还需要一个新的数组,所有出现过的值的集合,比如65 66 67 67最后就会收集成65 66 67

之后我们会遍历这个65 66 67 到映射表中去查,如果 查到不一致的数据了,就失败了(两个数组如果收集的不一致,也不行)

所以最后梳理一下整体的逻辑

两个 预备数组

1.映射数组(这个取值范围我就有点不太知道了,不过不太重要)

2.出现数组

我们遍历第一个String,拿到单个char,拿到单个int,给映射数组对应的位置 上+1,同时如果之前是0,那么就把这个int也加到出现数组里取,反之,不加

遍历第二个数组的时候,char,int,映射数组上对应的位置 不是0,就在对应位上的值-1。如果对应位置上 发现是0,就代表没出现过这个数,或者当前这个数组,这个值多了一个。 最后再根据出现数组到 映射数组里去找对应位,看看 是不是都为0了, 如果是,那么就成功了。

有没有更牛逼的方法?

我也就是一个猜想。因为我发现String的hashcode特别 神奇,他是怎么确保两个String各个位上的字符都相等,仅仅从hashcode 就可以判断出来呢?因为完全 可能有其他String不一样的,但是生成的值是一样的。

所以可以 得出结论:当前元素在数组中是第几个+当前元素的字符char的值——组成——>这个位上的代表值。同时累计的值是无法以另外形式拼凑出来的

看看它的源码

public int hashCode() {
    int h = hash;
    final int len = length();
    if (h == 0 && len > 0) {
        for (int i = 0; i < len; i++) {
            h = 31 * h + charAt(i);
        }
        hash = h;
    }
    return h;
}

hash默认是0

 每次遍历一位的时候, 都会把当前的hash值,乘以31, 加上当前位上的字符的ascii值。这似乎能保持其独一无二? 为什么?

如果不考虑int溢出的 话,每次乘以31都会上升一个量级,这区分了每一位,同时结合了charAt(i),所以这真的是很难拼凑出来的。(这个东西俺一时半会真的考虑不明白,先简略这么写吧)

同时溢出后,int很有可能会变成负数,所以会一直处于正向溢出,反向溢出的过程中。

反正这个hash 算法就是很牛逼,不可逆,还具有唯一性!

怎么借鉴到我们这个情形来呢?

我们 这个情形的挂钩点无关 位置了,有关于数字的大小和个数,并且不会被其他形式凑出来。

所以处理相同数字的时候,处理逻辑应该是相同的。

我们只需要让每个数字都有独一无二的值即可。

然后就没思路啦。。。哈哈。。。

猜你喜欢

转载自blog.csdn.net/qq_36523667/article/details/81368287