剑指 Offer 38: 字符串的排列

这道题一看就是使用回溯法,但是由于是排列,所以索引和组合不同(组合的索引是从start标志位开始),排列是从下标为0开始,并且需要借助排序!所以需要先转化成将String转化为char[]类型,然后借用Arrays类的sort函数进行排序,排除可能重复的项目。这里是参数出错:

这里错在List类型的变量判断长度是使用size函数。而且String类型的数组每个元素等于一个对String列表使用get()函数,然后将对应元素存进String数组中。

StringBuilder和StringBuffer的区别不仅只有速度和线程安全性的区别,还有调用函数的区别!delete是指定开始和结尾。

 

2023/8/24

这里一开始使用StringBuilder想来存结果不方便,因为StringBuilder存的信息是直接在结尾加上。所以要使用List来存储,然后再用List专有的get函数使用for循环一个个取出来。

 

这里要记住,List里可以存String类型的变量(泛型包括Integer,String,Character等)。然后将这个每次一个String(通过StringBuilder的toString()函数转化后)。千万记住最后创建String大小的时候是res的大小(有几个答案就创建几个空间)

List方法

List接口包括Collection接口的所有方法。 这是因为Collection是List的超级接口。

Collection接口中还提供了一些常用的List接口方法:

  • add() - 将元素添加到列表

  • addAll() - 将一个列表的所有元素添加到另一个

  • get() - 有助于从列表中随机访问元素

  • iterator() - 返回迭代器对象,该对象可用于顺序访问列表的元素

  • set() - 更改列表的元素

  • remove() - 从列表中删除一个元素

  • removeAll() - 从列表中删除所有元素

  • clear() - 从列表中删除所有元素(比removeAll()效率更高)

  • size() - 返回列表的长度

  • toArray() - 将列表转换为数组

  • contains() -  如果列表包含指定的元素,则返回true

当存储的临时空间长度满足目标长度时,就可以结束了并将这个存进结果集合了。如果不满足,就需要继续进行判断,如果当前值被访问过,或者当前值没有被访问过,但是前面的值也没有被访问过(说明这个循环已经结束)。保证相同的元素必须保持其相对顺序!!这就是为什么要将String类型的值转为CharArray然后进行排序,并且从左往右进行遍历的原因。然后在调用后复原visited和删除结尾的那个值(撤销),并且StringBuilder的撤销使用的是delete函数,第一个参数是开头位置,第二个是结尾位置,并且是左闭右开。

发现个比较神奇的点,就是在判断是否重复的时候,无论i>0 && !visited[i-1] && charArr[i]==charArr[i-1]中的条件visit[i-1]是访问过也好还是没访问过,其实都是可以得到答案的的。

当是!visited[i-1]时,说明没有被访问过,那么在第i个相同的元素是不能使用的,也就是官方题解中所说的,在最左边的相同元素使用了,后面的元素才能继续使用,这样就可以保证在左边的相同元素在所有排列中都是在左边的,比如说[a,b1,b2,c]出来的排列有[a,b1,b2,c],[a,b1,c,b2]....等等,但是不会出现[a,b2,b1,c],[a,b2,c,b1]这样的情况。也就是保证有序性,避免重复。

当是visited[i-1]时,说明被访问过了,那么为什么这样也能得到正确答案呢,是因为这样的条件是保证了首先排列最右边的相同元素,与上面恰好相反,这样的条件出来的排列会保证b2始终在b1左边。

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值