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 算法就是很牛逼,不可逆,还具有唯一性!
怎么借鉴到我们这个情形来呢?
我们 这个情形的挂钩点无关 位置了,有关于数字的大小和个数,并且不会被其他形式凑出来。
所以处理相同数字的时候,处理逻辑应该是相同的。
我们只需要让每个数字都有独一无二的值即可。
然后就没思路啦。。。哈哈。。。