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
}