字符串包含

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/shida_csdn/article/details/83539304

题目描述

给定两个分别由字母组成的字符串A和字符串B,字符串B的长度比字符串A短。请问,如何最快地判断字符串B中所有字母是否都在字符串A里?

为了简单起见,我们规定输入的字符串只包含大写英文字母,请实现函数bool StringContains(string &A, string &B)

比如,如果是下面两个字符串:

String 1:ABCD

String 2:BAD

答案是true,即String2里的字母在String1里也都有,或者说String2是String1的真子集。

如果是下面两个字符串:

String 1:ABCD

String 2:BCE

答案是false,因为字符串String2里的E字母不在字符串String1里。

同时,如果string1:ABCD,string 2:AA,同样返回true。

分析与解法

哈希查表法:

首先考虑基于 String 1 构造一个 Hash 结构,然后遍历 String 2,检查每个字符是否都在 Hash 中

又因为字母是有限的(26个英文字母),因此该 Hash 结构的大小是有限的,因此可以用一个整数(32位即可)的从低位到高位的每一位代表一个字符,例如最低位代表 ‘A’,第 26 位代表 ‘Z’,每一位为 1 时代表字母存在,为 0 代表不存在

通过整数的 & 运算就可以判断 Hash 结构中是否存在某个字母

举个例子:

ABCD 转为整数的二进制表示就为:00000000000000000000001111  

BCE,先看 B,转为二进制:00000000000000000000000010

00000000000000000000000010 & 00000000000000000000001111  != 0 

继续判断 C,转为二进制:00000000000000000000000100

00000000000000000000000100 & 00000000000000000000001111  != 0 

继续判断 E,转为二进制:00000000000000000000010000

00000000000000000000010000 & 00000000000000000000001111  == 0 

当出现按位与的结果为 0 时,可以判断 BCE 不在 ABCD 里

package main

import (
	"fmt"
)

func encode(str string) uint32 {
	var value uint32 = 0
	runes := []rune(str)
	for _, v := range runes {
		shift := uint32(v) - uint32('A')
		value |= 1 << shift
	}
	return value
}

func Contains(str1, str2 string) bool {
	val := encode(str1)
	for _, v := range ([]rune(str2)) {
		shift := uint32(v) - uint32('A')
		if val&(1<<shift) == 0 {
			return false
		}
	}
	return true
}

func main() {
	str1 := "ABCD"
	str2 := "CD"
	fmt.Println(Contains(str1, str2))
}

举一反三

1、变位词

  • 如果两个字符串的字符一样,但是顺序不一样,被认为是兄弟字符串,比如bad和adb即为兄弟字符串,现提供一个字符串,如何在字典中迅速找到它的兄弟字符串,请描述数据结构和查询过程。

     方法:先排序,再比较是否相等

package main

import "fmt"

func QuickSort(runes []rune, left, right int) {
	if left < right {
		m := part(runes, left, right)
		QuickSort(runes, left, m-1)
		QuickSort(runes, m+1, right)
	}
}

func part(runes []rune, left, right int) int {
	n := runes[left]
	for left < right {
		for left < right && runes[right] >= n {
			right--
		}
		runes[left] = runes[right]
		for left < right && runes[left] <= n {
			left++
		}
		runes[right] = runes[left]
	}
	runes[left] = n
	return left
}
func FindBrother(strs []string, str string) []string {

	var res []string

	strRunes := []rune(str)
	QuickSort(strRunes, 0, len(strRunes)-1)
	strSorted := string(strRunes)

	for _, v := range strs {
		tmp := []rune(v)
		QuickSort(tmp, 0, len(tmp)-1)
		if strSorted == string(tmp) {
			res = append(res, v)
		}
	}

	return res
}
func main() {
	strs := []string{"abc", "cba", "agt"}
	fmt.Println(FindBrother(strs, "bac"))
}

猜你喜欢

转载自blog.csdn.net/shida_csdn/article/details/83539304