s
func lengthOfLongestSubstring1(s string) int {
dic := map[byte]int{}
length, i := 0, -1
for j := 0; j < len(s); j++ {
if _, ok := dic[s[j]]; ok {
//更新左指针 i,dic[s[j]]上一次字符s[j]的索引
if dic[s[j]]> i{
i= dic[s[j]]
}
}
dic[s[j]] = j // 哈希表记录索引
// 更新结果
if length <j-i{
length = j-i
}
}
return length
}
2、数组中的重复数字:给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
第一种解法:先排序再扫描。从排好序的数组进行遍历,记录当前位置与其之前位置的数进行比较,若相等则输出该数。
时间复杂度:O(nlogn);空间复杂度O(1)
第二种解法:对数组进行遍历,每次判断哈希表中是否含有该元素,若有,输出此元素。若最后哈希表中的元素数量与数组中的相同,表面无重复数据。
时间复杂度:O(n);空间复杂度O(n)
时间复杂度必须是O(n),并且空间复杂度为O(1)的条件
第三种解法:
答案是使用 位操作Bit Operation 来解此题。
将所有元素做异或运算,即a[1] ⊕ a[2] ⊕ a[3] ⊕ …⊕ a[n],所得的结果就是那个只出现一次的数字,时间复杂度为O(n)。
go 位运算
- & 按位与运算
- | 按位或运算
- ^ 按位异或运算
- << 左移运算符,由"<<"右边的数指定移动的位数,高位丢弃,低位补0。左移n位就是乘以2的n次方。
- >> 右移运算符,">>"右边的数指定移动的位数,低位舍弃,高位补0。右移n位就是除以2的n次方。
用于运算构成整数的每个二进制位,就是位上0,1的运算。
package main
import (
"fmt"
)
func main() {
nums := []int{1, 2, 2, 3, 1, 4, 4, 5, 5}
soloNumber(nums)
}
func soloNumber(nums []int) (solo int) {
for _, elem := range nums {
solo = solo ^ elem
}
fmt.Println("solo", solo)
return solo
}
编译输出:
>>solo 3
3、LeetCode389:找不同
给定两个字符串 s 和 t,它们只包含小写字母。
字符串 t 由字符串 s 随机重排,然后在随机位置添加一个字母。
请找出在 t 中被添加的字母。
示例 1:
输入:s = "abcd", t = "abcde"
输出:"e"
解释:'e' 是那个被添加的字母。
示例 2:
输入:s = "", t = "y"
输出:"y"
示例 3:
输入:s = "a", t = "aa"
输出:"a"
示例 4:
输入:s = "ae", t = "aea"
输出:"a"
知识点:不同编码方式1个英文字母占的字节是不同的:
1.ASCII码:英文字dao母(无大小写)占一个zhuan字节的空间,中shu文字符占两个字节的空间。
2.utf-8编码:一个英文字符等于一个字节,一个中文(含繁体)等于三个字节。中文的标点符号需要三个字节,英文的标点符号需要一个字节。go使用(utf-8编码)
3.Unicode编码:英文编码是两个字节,中文编码是两个字节。标点符号在汉语中占两个字节,在英语中占两个字节。
func findTheDifference(s, t string) string {
letterASCII := map[int]string{97: "a", 98: "b", 99: "c", 100: "d", 101: "e",
102: "f", 103: "g", 104: "h", 105: "i", 106: "j", 107: "k", 108: "l", 109: "m",
110: "n", 111: "o", 112: "p", 113: "q", 114: "r", 115: "s", 116: "t", 117: "u",
118: "v", 119: "w", 120: "x", 121: "y", 122: "z"}
var diff byte
for i := range s {
fmt.Println("i", i, s[i], t[i])
diff ^= s[i] ^ t[i]
}
val := int(diff ^ t[len(t)-1])
alphabet := letterASCII[val]
return alphabet
}
测试:
fmt.Println(findTheDifference("afvvvvb", "hafvvvvb"))
>>h
方法二:求和
将字符串 s 中每个字符的 ASCII 码的值求和,得到 As;对字符串 t 同样的方法得到 A t。两者的差值 At_As
即代表了被添加的字符。
4、给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。
示例: 给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
func main() {
nums := []int{2, 7, 11, 15}
target := 9
fmt.Println(twonum(nums, target))
}
func twonum(nums []int, target int) []int {
hashTable := map[int]int{}
for i, x := range nums {
if p, ok := hashTable[target-x]; ok {
log.Info(p, ok)
return []int{p, i}
}
hashTable[x] = i
}
return nil
}
5、找出字符串中第一个只出现一次的字母.返回其索引,若不存在,则返回-1。
思路:首先,遍历字符串,统计每个字符出现的频率,并存入map中。然后,再次遍历字符串串中的字符,如果该字符出现频率为1,return该字符的索引。如果不存在则返回-1.
func firstAppearOnceTime(s string) int {
count := map[rune]int{}
//统计每个字母的出现的次数,存入map
for _, alph := range s {
count[alph] += 1
}
//遍历字符串,判断其频率是否==1,如果是return索引,否则返回-1
for index, v := range s {
if count[v] == 1 {
fmt.Println(string(v))
return index
}
}
return -1
}