题目:验证栈序列
题目描述:
给定 pushed 和 popped 两个序列,只有当它们可能是在最初空栈上进行的推入 push 和弹出 pop 操作序列的结果时,返回 true;否则,返回 false 。
示例 1:
输入:pushed = [1,2,3,4,5], popped = [4,5,3,2,1]
输出:true
解释:我们可以按以下顺序执行:
push(1), push(2), push(3), push(4), pop() -> 4,
push(5), pop() -> 5, pop() -> 3, pop() -> 2, pop() -> 1
示例 2:
输入:pushed = [1,2,3,4,5], popped = [4,3,5,1,2]
输出:false
解释:1 不能在 2 之前弹出。
分析:就是模拟栈的进栈出栈,大概思路就是,初始化一个切片res,存放进栈元素,初始化一个cnt,标识正确出栈元素的数量,根据不同的情况进行操作,首先如果res不是空的,res的最后一个元素等于出栈的第一个元素,那就将res最后一个元素去掉,cnt++;如果popped[j]==pushed[i],直接不需要进栈,cnt++;最后就是需要进栈的操作了。说的比较不清楚,没关系看代码就好了
代码:
func validateStackSequences(pushed []int, popped []int) bool {
res:=[]int{}
cnt:=0
i:=0
j:=0
for j<len(popped){
if len(res)!=0 && res[len(res)-1]==popped[j]{
j++
res=res[:len(res)-1]
cnt++
}else if i<len(pushed) && popped[j]==pushed[i]{
i++
j++
cnt++
}else{
if i==len(pushed){
return false
}
res=append(res,pushed[i])
i++
}
}
if cnt==len(pushed){
return true
}
return false
}
题目:全排列
题目描述:
给定一个没有重复数字的序列,返回其所有可能的全排列。
示例:
输入: [1,2,3]
输出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
分析:一开始想的用回溯法,不知道为什么go语言一直出错,后来看了人家的代码,用了递归,大致的意思就是每次选出一个元素作为开头的元素,然后最后只剩一个了,再加上上次选中的,再进行交换,一级一级递推
代码:
func permute(nums []int) [][]int {
n:=len(nums)
res:=make([][]int,0)
if n==0{
return nil
}
if n==1{
return append(res,[]int{nums[0]})
}
for i:=0;i<n;i++{
swap(&nums[0],&nums[i])
sans:=permute(nums[1:])
for _,v:=range sans{
v=append(v,nums[0])
L:=len(v)
for k:=0;k<L/2;k++{
swap(&v[k],&v[L-1-k])
}
res=append(res,v)
}
swap(&nums[0],&nums[i])
}
return res
}
func swap(nums1 ,nums2*int){
if nums1==nums2{
return
}
temp:=*nums1
*nums1=*nums2
*nums2=temp
}
题目:报数
题目描述:
报数序列是一个整数序列,按照其中的整数的顺序进行报数,得到下一个数。其前五项如下:
-
1
-
11
-
21
-
1211
-
111221
1 被读作 “one 1” (“一个一”) , 即 11。
11 被读作 “two 1s” (“两个一”), 即 21。
21 被读作 “one 2”, “one 1” (“一个二” , “一个一”) , 即 1211。
给定一个正整数 n(1 ≤ n ≤ 30),输出报数序列的第 n 项。
注意:整数顺序将表示为一个字符串。
示例 1:
输入: 1
输出: “1”
示例 2:
输入: 4
输出: “1211”、
分析:还是递归,确定的就是1返回的是”1“,然后通过遍历,记录重复次数,遇到不一样的就进行一次拼接,strconv.Itoa(repeatCount),int转换成字符串
代码:
func countBefore(s string) string {
resStr := ""
// 本质上是对每个数字用重复次数+重复的数字然后拼起来
repeatCount := 1
for i := 0; i < len(s); i++ {
if i+1 < len(s) && s[i] == s[i+1] {
// 寻找出现重复的数字,累计重复次数
// 如果运行到末尾,且末尾不是重复数字的情况也是执行else的逻辑
// 如果末尾和之前的重复,那么会被repeatCount记录
repeatCount++
} else {
resStr += strconv.Itoa(repeatCount) + string(s[i])
// 重置重复次数
repeatCount = 1
}
}
return resStr
}
func countAndSay(n int) string {
if n == 1 {
return "1"
}
return countBefore(countAndSay(n - 1))
}
题目:压缩字符串
题目描述:
在完成原地修改输入数组后,返回数组的新长度。
进阶:
你能否仅使用O(1) 空间解决问题?
示例 1:
输入:
[“a”,“a”,“b”,“b”,“c”,“c”,“c”]
输出:
返回6,输入数组的前6个字符应该是:[“a”,“2”,“b”,“2”,“c”,“3”]
说明:
"aa"被"a2"替代。"bb"被"b2"替代。"ccc"被"c3"替代。
示例 2:
输入:
[“a”]
输出:
返回1,输入数组的前1个字符应该是:[“a”]
说明:
没有任何字符串被替代。
示例 3:
输入:
[“a”,“b”,“b”,“b”,“b”,“b”,“b”,“b”,“b”,“b”,“b”,“b”,“b”]
输出:
返回4,输入数组的前4个字符应该是:[“a”,“b”,“1”,“2”]。
说明:
由于字符"a"不重复,所以不会被压缩。"bbbbbbbbbbbb"被“b12”替代。
注意每个数字在数组中都有它自己的位置。
注意:
所有字符都有一个ASCII值在[35, 126]区间内。
1 <= len(chars) <= 1000。
分析:这道题和上一道题有相似的地方,就是要记录重复字数,需要在原来的切片上进行改动,不能申请额外空间,不多说了,看代码吧,需要注意的就是int转换成byte,我是先转换成string,再转换成byte
代码:
func compress(chars []byte) int {
count :=1
if len(chars)==0 || len(chars)==1{
return len(chars)
}
cur:=0
for i:=1;i<len(chars);i++{
if chars[i]==chars[cur]{
count++
}else{
if count>1{
str:=strconv.Itoa(count)
for j:=0;j<len(str);j++{
cur++
chars[cur]=byte(str[j])
}
count=1
}
cur++
chars[cur]=chars[i]
}
}
if count>1{
str:=strconv.Itoa(count)
for j:=0;j<len(str);j++{
cur++
chars[cur]=byte(str[j])
}
}
chars=chars[:cur+1]
return cur+1
}