数据结构-字符串

字符串(string)

定义及操作

Go中的字符串是一个字节的切片。可以通过将其内容封装在 "" 中来创建字符串。Go中的字符串是Unicode兼容的,并且是UTF-8编码的,每一个字符都用一个或者多个字节表示(当字符为 ASCII 码表上的字符时则占用 1 个字节,其它字符根据需要占用 2-4 个字节)。

UTF-8 是一种被广泛使用的编码格式,是文本文件的标准编码,其中包括 XMLJSON 在内也都使用该编码。由于该编码对占用字节长度的不定性,在Go语言中字符串也可能根据需要占用 1 至 4 个字节,这与其它编程语言如java,python,c++等不同(Java 始终使用 2 个字节)。Go语言这样做不仅减少了内存和硬盘空间占用,同时也不用像其它语言那样需要对使用 UTF-8 字符集的文本进行编码和解码。

基本使用:

func main() {  
    name := "Hello World"
    fmt.Println(name)
}

访问字符串中单个字节:

func main() {  
    s := "Hello World"
    for i:= 0; i < len(s); i++ {
        fmt.Printf("%d ", s[i]) // 十进制形式输出
    }
    
    fmt.Printf("\n")
    
    for i:= 0; i < len(s); i++ {
        fmt.Printf("%c ",s[i])  // 字符形式输出
    }
}

比较函数:

在golang中字符串之间是可以用<,>,==,!=,<=,>= 进行比较的

可变性:

golang中的字符串是不可变的,但支持 + 级联操作和 += 追加操作

text1 := "Hello" + " GoLang"
text1 += " Java"
fmt.Println(text1) // 输出 Hello GoLang Java

注意,作为不可变字符串在修改字符串中字符时时间复杂度较高

转义字符:

符串中可以使用转义字符来实现换行、缩进等效果,常用的转义字符包括:

  • \n:换行符
  • \r:回车符
  • \t:tab 键
  • \u\U:Unicode 字符
  • \\:反斜杠自身

相关包:

  • strings

  • strconv --- 字符串格式转换

字符索引:

与数组相同,采用标准索引法,但注意获取字符串中某个字节的地址属于非法行为,例如&str[1]


练习

二进制求和

给你两个二进制字符串,返回它们的和(用二进制表示)。

输入为 非空 字符串且只包含数字 10

示例 1:

输入: a = "11", b = "1"
输出: "100"

示例 2:

输入: a = "1010", b = "1011"
输出: "10101"

提示:

  • 每个字符串仅由字符 '0''1' 组成。
  • 1 <= a.length, b.length <= 10^4
  • 字符串如果不是 "0" ,就都不含前导零。
  • 在Golang中,一个 数字字符字符 0 相减,得到的值就是这个数字字符的数值,即 ‘9’ - ‘0’ = 9

解:

func addBinary(a string, b string) string {
   
/*
    算法没有使用 strconv.Itoa(int->string)与 strconv.Atoi(string -> int)
    二进制求和,逐位计算,字符串从尾部向前遍历相加,
    同时存储进位carry,将其累加到下一次计算。
*/
	
    // 相加字符串
	result := ""
	// 存储进位
	carry := 0

	// 字符串长度
	i, j := len(a)-1, len(b)-1

	// 遍历两个字符串
	for i >= 0 || j >= 0 {

		t1, t2 := 0, 0 // 每次循环开始都置零(考虑到相加字符串长度不同)

		// 将a,b中字符转换为数值
		if i >= 0 {
			t1 = int(a[i] - '0')
		}
		if j >= 0 {
			t2 = int(b[j] - '0')
		}

		// 当前位相加 + 进位
		sum := t1 + t2 + carry

		// 按位相加的4种情况
		switch sum {
		case 3:
			carry = 1
			result = "1" + result
		case 2:
			carry = 1
			result = "0" + result
		case 1:
			carry = 0
			result = "1" + result
		case 0:
			carry = 0
			result = "0" + result
		}
		// 每次遍历后,字符串长度-1
		i--
		j--
	}

	// 若遍历完字符串后依旧存在进位
	if carry == 1 {
		result = "1" + result
	}
	return result
}

实现 strStr()

实现strStr函数。

给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1

示例 1:

输入: haystack = "hello", needle = "ll"
输出: 2

示例 2:

输入: haystack = "aaaaa", needle = "bba"
输出: -1

说明:

needle 是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。

对于本题而言,当 needle 是空字符串时我们应当返回 0 。这与C语言的strstr()以及 JavaindexOf()定义相符。

func strStr(haystack string, needle string) int {

/*	
	沿着字符换逐步移动滑动haystack字符串,将haystack内的子串与 needle 字符串比较
*/

	h, n := len(haystack), len(needle)

	for i := 0; i < h-n+1; i++ {
		if haystack[i:i+n] == needle {
			return i
		} 
	}
	return -1  
}

最长公共前缀

编写一个函数来查找字符串数组中的最长公共前缀。

如果不存在公共前缀,返回空字符串 ""

示例 1:

输入: ["flower","flow","flight"]
输出: "fl"

示例 2:

输入: ["dog","racecar","car"]
输出: ""
解释: 输入不存在公共前缀。

说明:

所有输入只包含小写字母 a-z

func longestCommonPrefix(strs []string) string {
    
/*
	以第一个字符串为基准,依次在所有字符串进行比较,
	比较时如果基准元素被字符串包含并在其首位(strings.Index(str,prefix) == 0),
	则更新基准元素,直到所有的字符串拥有相同的基准元素,即最大前缀
*/
    
	// 如果输入切片为空,则返回空字符串
	if len(strs) < 1 {
		return ""
	}
	
	// prefix为切片中首个字符串
	prefix := strs[0]
	
	// 遍历输入切片,str为字符串
	for _, str := range strs {
		// 判断在prefix在str中首次出现的位置,若=0,则prefix为最大前缀
		
		for strings.Index(str, prefix) != 0 {
			// 如果prefix长度减为0,证明各字符串没有相同前缀,返回空字符串
			
			if len(prefix) == 0 {
				return ""
			}
			// 删去尾部字符
			prefix = prefix[:len(prefix)-1]
		}
	}
	return prefix
}
posted @ 2020-05-28 13:31  侠奢  阅读(338)  评论(0)    收藏  举报