字符串算法
字符串算法
1.反转字符串
/*
题目:反转字符串
leetcode:344
输入:"hello word"
输出:"drow olleh"
思路:前后换位置
*/
func reverseString(s []byte) {
lenth := len(s)
for i := 0; i < lenth/2; i++ {
s[i], s[lenth-i-1] = s[lenth-i-1], s[i]
}
}
func main() {
s := "hello word"
byteS := []byte(s)
reverseString(byteS)
fmt.Println(string(byteS))
}
2.字符串中的第一个唯一字符
/*
题目:字符串中的第一个唯一字符
leetcode:387
输入: s = "leetcode"
输出: 0
输入: s = "loveleetcode"
输出: 2
输入: s = "aabb"
输出: -1
思路:进行两次遍历,第一次遍历利用map统计每个字符出现的次数,第二次遍历把只出现一次的字符索引返回
*/
func firstUniqChar(s string) int {
m := map[rune]int{}
for _, v := range s {
m[v]++
}
for k, v := range s {
if m[v] == 1 {
return k
}
}
return -1
}
func main() {
s := "leetcode"
n := firstUniqChar(s)
fmt.Println(n)
}
3.有效的字母异位词
/*
题目:有效的字母异位词
leetcode:242
输入: s = "anagram", t = "nagaram"
输出: true
输入: s = "rat", t = "car"
输出: false
思路:对两个字符串统计次数,然后对比两个map是否一样。用反射
*/
func isAnagram(s string, t string) bool {
m1 := map[rune]int{}
m2 := map[rune]int{}
for _, v := range s {
m1[v]++
}
for _, v := range t {
m2[v]++
}
return reflect.DeepEqual(m1, m2)
}
/*
解法2:两个字符串排序,比较排序后的字符串是否一致
*/
func isAnagram2(s string, t string) bool {
s1, s2 := []byte(s), []byte(t)
sort.Slice(s1, func(i, j int) bool {
return s1[i] < s1[j]
})
sort.Slice(s2, func(i, j int) bool {
return s2[i] < s2[j]
})
return string(s1) == string(s2)
}
func main() {
s := "anagram"
s2 := "nagaram"
n := isAnagram2(s, s2)
fmt.Println(n)
}
4.验证回文串
/*
题目:验证回文串
leetcode:125
输入: s = "A man, a plan, a canal: Panama"
输出:true
解释:"amanaplanacanalpanama" 是回文串。
思路:
1.字符串全部转大写
2.过滤其他非字符数字字符
3.过滤之后对字符串倒序排列
4.对比过滤前与过滤后的字符串是否一致
*/
func isPalindrome(s string) bool {
s = strings.ToUpper(s)
li := []rune{}
//过滤非字符数字字符
for _, v := range s {
if (v >= 65 && v <= 90) || (v >= 48 && v <= 57) {
li = append(li, v)
}
}
li2 := make([]rune, len(li))
copy(li2, li)
//新的li2倒序
for i := 0; i < len(li2)/2; i++ {
li2[i], li2[len(li2)-1-i] = li2[len(li2)-1-i], li2[i]
}
return string(li) == string(li2)
}
func main() {
s := "A man, a plan, a canal: Panama"
//s := "race a car"
n := isPalindrome(s)
fmt.Println(n)
}
5.找出字符串中第一个匹配项的下标
/*
题目:找出字符串中第一个匹配项的下标
leetcode:28
输入:haystack = "sadbutsad", needle = "sad"
输出:0
解释:"sad" 在下标 0 和 6 处匹配。
思路:遍历匹配第一个字符,匹配上了之后截取s1,长度为s2的长度,然后与s2比较,匹配上了返回下标,否则继续遍历下一个字符
*/
func strStr(s1 string, s2 string) int {
len1, len2 := len(s1), len(s2)
if len2 > len1 {
return -1
}
for i := 0; i < len1; i++ {
if s1[i] == s2[0] {
//首字母匹配上了,从s1截取与s2比较
index := i + len2 //截取停止的位置下标
if index > len1 {
//超出索引范围
return -1
}
if s1[i:index] == s2 {
return i
}
}
}
return -1
}
func main() {
s1 := "a"
s2 := "a"
n := strStr(s1, s2)
fmt.Println(n)
}
6.无重复字符的最长子串
/*
题目:无重复字符的最长子串
leetcode:3
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
思路:
1.遍历一遍字符串,依次以每个字母开头。截取 s[index:]
2.字典取值,不存在则把值存进map中,存在则清空map
3.字典数量最多的就是无重复字符串
*/
func demo(s string) (count int, str string) {
dic := make(map[byte]byte)
st := []byte{}
for i := 0; i < len(s); i++ {
s2 := s[i:]
st2 := []byte{}
for k := range s2 {
_, ok := dic[s2[k]]
if ok {
dic = make(map[byte]byte) //清空map
st2 = []byte{}
break
} else {
dic[s2[k]] = s2[k]
st2 = append(st2, s2[k])
}
if len(st2) > len(st) {
st = st2
}
}
}
return len(st), string(st)
}
func main() {
a, b := demo("abcc")
fmt.Println(a)
fmt.Println(b)
}
7.判断路径是否相交
/*
题目:判断路径是否相交
leetcode:1496
给你一个字符串 path,其中 path[i] 的值可以是 'N'、'S'、'E' 或者 'W',分别表示向北、向南、向东、向西移动一个单位。
输入:path = "NES"
输出:false
解释:该路径没有在任何位置相交。
输入:path = "NESWW"
输出:true
解释:该路径经过原点。
思路:起始坐标(0,0),把走过的坐标用map保存,如果坐标重复,说明相交
*/
func isPathCrossing(path string) bool {
//'N'、'S'、'E' 或者 'W',分别表示向北、向南、向东、向西移动一个单位
dirs := map[byte][]int{
'N': {0, 1},
'S': {0, -1},
'W': {1, 0},
'E': {-1, 0},
}
x, y := 0, 0 //初始坐标0,0
m := map[string]struct{}{"0,0": {}} //记录已经走过的坐标
for i := 0; i < len(path); i++ {
dir := dirs[path[i]]
x, y = x+dir[0], y+dir[1]
mStr := fmt.Sprintf("%d,%d", x, y)
_, ok := m[mStr]
if ok {
//坐标存在
return true
} else {
//坐标不存在
m[mStr] = struct{}{}
}
}
return false
}
func main() {
s := "NESWW"
n := isPathCrossing(s)
fmt.Println(n)
}
选择了IT,必定终身学习