字符串算法

字符串算法

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)
}
posted @ 2024-01-30 18:41  Jeff的技术栈  阅读(7)  评论(0编辑  收藏  举报
回顶部