题目:数数并说
描述:报数序列是指一个整数序列,按照其中的整数的顺序进行报数,得到下一个数。其前五项如下:
1. 1
2. 11
3. 21
4. 1211
5. 111221
1 被读作 "one 1" ("一个一") , 即 11。
11 被读作 "two 1s" ("两个一"), 即 21。
21 被读作 "one 2", "one 1" ("一个二" , "一个一") , 即 1211。
给定一个正整数 n ,输出报数序列的第 n 项。
注意:整数顺序将表示为一个字符串。
案例1:
输入: 1
输出: "1"
案例2:
输入: 4
输出: "1211"
方案一:使用字符串获取子串比较
外层循环正整数n,内层循环获取到的字符串,比较前一位和后一位,相同则增加count,然后再拼接字符串
代码一:
func countAndSay(_ n: Int) -> String {
var say = "1"
for _ in 1..<n {
var cnt = 1
var tempSay = ""
for j in 0..<say.count {
if (say.substingInRange(j..<j+1) == say.substingInRange(j+1..<j+2)) {
cnt += 1
} else {
tempSay += String(cnt) + String(say.substingInRange(j..<j+1)!)
cnt = 1
}
}
say = tempSay
}
return say
}
extension String {
//获取子字符串
func substingInRange(_ r: Range<Int>) -> String? {
if r.lowerBound < 0 || r.upperBound > self.count {
return nil
}
let startIndex = self.index(self.startIndex, offsetBy:r.lowerBound)
let endIndex = self.index(self.startIndex, offsetBy:r.upperBound)
return String(self[startIndex..<endIndex])
}
}
Swift中取范围内字符子串参考:Swift4 获取String子字符串这里直接把代码拷过来了
执行用时不截图了:1276ms、、、
方案二:将字符串转成数组,使用下标比较
思想和方法一是一致的,但明显取下标方便,然后数组效率比字符串要高
代码二:
func countAndSay(_ n: Int) -> String {
var say = "1"
if n == 1 {
return say
}
for _ in 1..<n {
var tempSay = ""
var cnt = 1
var chars = Array(say)
for j in 0..<say.count {
//条件太长还是括起来比较好
if (j + 1 < chars.count && chars[j] == chars[j + 1]) {
cnt += 1
} else {
tempSay.append("\(cnt)")
tempSay.append(chars[j])
cnt = 1
}
}
say = tempSay
}
return say
}
执行用时:32ms,比方案一提高了太多
方案三:也不算什么方案、、、看了提交记录的第一名,对上方方案二优化了一下、、
就减少了一次循环、、、
代码三:
func countAndSay2(_ n: Int) -> String {
var say = "1"
if n == 1 {
return say
}
for _ in 1..<n {
var tempSay = ""
var cnt = 1
var chars = Array(say)
var current = chars[0]
for j in 1..<say.count {
if chars[j] == current {
cnt += 1
} else {
tempSay.append("\(cnt)")
tempSay.append(current)
cnt = 1
current = chars[j]
}
}
tempSay.append("\(cnt)")
tempSay.append(current)
say = tempSay
}
return say
}
结果又快了那么一点点、、、没啥影响、、