LeetCode_392刷题笔记

1原题目
LeetCode_392
2 题目大意
给定字符串 s 和 t ,判断 s 是否为 t 的子序列。
你可以认为 s 和 t 中仅包含英文小写字母。字符串 t 可能会很长(长度 ~= 500,000),而 s 是个短字符串(长度 <=100)。
字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一个子序列,而"aec"不是)。
3.题目分析
在这里插入图片描述
4基础知识
贪心算法,二分查找,双指针
4.1C的语法
4.2数据结构
4.3算法
贪心法(解法2)
把s的字符依次和t的字符匹配,匹配到s就下移,无论是否匹配,
t的下标都下移,匹配完s,说明s是t的子序列,否则不是。
时间O(max(M,N))

二分法(解法3)
对于挑战问题,对于相同的t,有10亿个s等待判断,每次都贪心去
匹配,效率就一般般了,还有更好的办法吗?

上面已经是线性的解法了,我们只能想logN的算法了,只有二分搜索。

二分搜索的前提是有序排列,这里没有有序排列,如何是好?

那就构造有序排列。字母a在t中出现的下标,可以是有序排列,
同样其他字母在t中出现的下标,分别都可以是有序排列。
这样就有26个有序排列了。

假如s[0]出现在了t的下标5,s[1]就必须在5之后,可以对s[1]这个字符
的所有下标进行查找刚好大于5的下标,既然是有序搜索,就可以是二分查找。

5解法
(1)简洁明了

int isSubsequence(char * s, char * t){
    while(true){
        if(!*s) return true;
        if(!*t) return false;
        if(*t++ == *s) s++;
    }
}

(2)贪心法(GO)

func isSubsequence(s string, t string) bool {
	i := 0
	for j := 0; j < len(t) && i < len(s); j++ {
		if s[i] == t[j] {
			i++
		}
	}

	return i >= len(s)
}

(3)二分法

func isSubsequence(s string, t string) bool {
	idxs := make([][]int, 26, 26)
	for i := 0; i < len(t); i++ {
		id := t[i] - 'a'
		idxs[id] = append(idxs[id], i)
	}

	target := -1
	for i := 0; i < len(s); i++ {
		ids := idxs[s[i]-'a']
		l, r := 0, len(ids)
		for l < r {
			mid := l + (r-l)/2
			if ids[mid] > target {
				r = mid
			} else {
				l = mid + 1
			}
		}

		//fmt.Println(s[i], l)

		if l < len(ids) && ids[l] > target {
			target = ids[l]
		} else {
			// 找不到符合的s[i]
			return false
		}
	}

	return true
}

6.总结
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值