用两个简单例子探究字符串相关问题中new int[128]的使用(java实现)

在字符串相关问题中,我们常常遇到需要统计字符出现的次数,判断字符是否出现过等问题.而我们常常想到的粗暴解法是O(n^2)的,即对每一个元素,都要遍历字符串,来求他的出现次数;或者遍历他前面的所有元素,看他是否出现过.毫无疑问,这些方法都是及其耗时的,也需要额外的变量来存放出现次数等相关信息.这时候,我们可以new一个128个元素的辅助数组,帮助我们在线性时间复杂度和常熟空间复杂度内达到同样的目的.下面用两个简单的例子来说明.
1.求一个字符串当中第一个只出现一次的元素.
在这里插入图片描述
正常情况下首先想到的暴力解法:对每个字符都分别遍历整个字符串,发现有只出现一次的元素就返回,一直没找到就返回-1.时间复杂度O(n^2),不需要额外空间。
我们再来使用上面提到的128位辅助数组。这里巧妙的利用了ascii码字符只有128种取值的特性。对字符串进行遍历,让辅助数组temp在当前字符对应位置上的取值++,就能统计该种字符的出现次数。(temp[k]++,k是当前字符的ascii码值)。这样我们在O(n)内就完成了统计。在对字符串进行一次遍历,一边遍历一边访问辅助数组temp,从里面读取字符的出现次数,遇到只出现过一次的就可以返回了。
在这里插入图片描述
2.同构字符串问题。
在这里插入图片描述
这里提供一种我自己想出来的比较奇怪的解法(肯定不是最优),同时也要兼顾上面所提到的想法。
拿到这道题的时候,我还是先想能不能把它转化为简单直接一点的问题,做了一些尝试但是没有AC。最后想到的这种方法其实很直接,就是直接对题目要求进行翻译。题目要求两个字符串的相同位置上的字符有对应关系,并且满足不能1对2,不能2对1等等要求。我想使用某种方法直接来刻画这种映射。同时需要保证算法在线性时间复杂度内完成。
字符串s的每一个元素有128个可能取值,字符串t也是一样。我们考虑构造一个128*128的二维数组temp。循环遍历s字符串,并把temp[s[i]][t[i]]设置为1,代表存在一个s[i]到t[i]的映射。这样遍历完一遍后,temp里面就存放了所有的对应关系。
之后对temp二维数组进行遍历。容易发现,题目中提到的“一个字符不能对应多个字符”“多个不同字符不能对应一个字符”在二维数组中的表现形式就是:同一行或者同一列不能出现两个及以上的1.因此对二维数组进行按行遍历,按列遍历即可。这个过程看似复杂,但却是常数时间复杂度。temp的大小是固定的。
算法时间复杂度:O(n)
=O(n)(遍历字符串,往temp中填入数据)+O(1)(按行,列遍历temp)
空间复杂度:O(1)(temp一直都是128 * 128)

在这里插入图片描述
效果展示:
在这里插入图片描述
这个方法其实还是一种比较简单粗暴的对题目条件的翻译,但是通过128*128的二维数组(与开头提到的想法有高度相通之处),将时间复杂度降低到一阶,更体现了这种技巧的威力。

总结:
无论是直接使用new int[128]还是第二题的变种,这个技巧都充分的利用了字符串每位上元素取值有限的特点,有力的解决了计数,统计字符相关信息不方便的问题(可以看到利用二维数组还能处理类似映射的问题),提供了将问题时间复杂度减小到一阶的有力工具。本质上是一种哈希,体现了哈希的思想在字符串当中的灵活使用。本人能力有限,上两题应该都有更加优化的解法,欢迎大佬们批评指正,希望对小伙伴们有帮助!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值