leetcode刷题笔记三 最长不重复子串 Scala版本
leetcode刷题笔记三 最长不重复子串 Scala版本
原地址:[https://leetcode.com/problems/longest-substring-without-repeating-characters/]:最长不重复子串
问题描述
题干:
Given a string, find the length of the longest substring without repeating characters.
例子
Input: "abcabcbb" Output: 3 Explanation: The answer is "abc", with the length of 3.
简要思路分析:
1.暴力法
2.结合动态规划的思想,在对字符串的遍历过程中,分析收到的字符是否已经获得,如果不是,对应的位置length+1, maxLength继续更新;如果是,将最长串的from+1。
a b c a b c b b 1 2 3 3 3 3 2 1
代码补充:
import scala.collection.mutable.Set
object Solution {
def lengthOfLongestSubstring(s: String) = {
var length = 0
var maxLength = 0
var prePose = 0
var mMap = Map[Int, Int]()
var mSet = Set(s(0))
mMap += (0->1)
if (s == null || s.length == 0){
null
}
for (i <- 1 until s.length){
if (mSet.contains(s(i))){
val from:Int = s.substring(prePose,i).indexOf(s(i)) + prePose
val to:Int = i
length = to - from
prePose = from + 1
mMap += (i->length)
}
else{
mSet.add(s(i))
var temp = mMap(i-1)+1
mMap += (i->temp)
length += 1
println("Pass")
}
if(length>=maxLength){
maxLength = length
}
}
maxLength
}
}
通过Map记录位置与length对应关系,通过Set记录哪些元素被访问过,使用prePose记录from侧位置,通过判断当前位置字符是否在Set中,更新prePose位置和length长度。代码整体并不复杂。
在提交leetcode过程中,能够实现AC,但执行时间较长。在讨论板块找到了简化版本,对其进行一定改动。这里附上。
import scala.collection.mutable.Map
object Solution {
def lengthOfLongestSubstring(s: String) = {
val map = Map[Char, Int]()
var from = 0
var length = 0
var maxLength = 0
var iper = 0
for((char,to) <- s.zipWithIndex){
map get char match{
case None => maxLength = maxLength max(to - from + 1)
case Some(i) => {
// 如果重复字符位置较当前from位置靠近字符串首,不进行调整,否则对from位置进行更新
if (i >= iper) {
iper = i
};
from = from max (iper + 1);
//确保保持maxLength更新
length = to - from + 1
if(length > maxLength){
maxLength = length
};
}
}
map += (char->to)
}
maxLength
}
}
//使用Set版本,滑动窗口
import scala.collection.mutable
object Solution {
def lengthOfLongestSubstring(s: String): Int = {
var set = mutable.Set[Char]()
var left = 0
var right = 0
var ans = 0
while (right < s.length){
val tempChar = s(right)
if (set.contains(tempChar) == false){
set += tempChar
right += 1
}
else{
while (left < right && set.contains(tempChar)){
set -= s(left)
left += 1
println("left: " + left)
}
set += tempChar
right += 1
}
ans = Math.max(ans, right - left)
}
return ans
}
}
func lengthOfLongestSubstring(s string) int {
heap := map[byte]int{}
res := 0
for i, j:= 0, 0; i < len(s); i++ {
heap[s[i]] += 1
for (heap[s[i]] > 1) {
heap[s[j]] -= 1
j += 1
}
res = max(res, i-j+1)
}
return res
}
func max(a int, b int) int {
if (a > b) {
return a
} else {
return b
}
}
知识补充:
在对比两种实现过程中,了解到了zipWithIndex用法
计数器 -- zip或zipWithIndex方法自动创建一个计数器
1.可以通过for循环打印
for((char,to) <- s.zipWithIndex){ println("char: " + char.toString + " " + "to: " + to.toString) } console: char: a to: 0 char: b to: 1 char: c to: 2 char: a to: 3 char: b to: 4 char: c to: 5 char: b to: 6 char: b to: 7
zip Stream 指定开始值
for((char,to) <- s.zip(Stream from 1)){ println("char: " + char.toString + " " + "to: " + to.toString) } console: char: a to: 1 char: b to: 2 char: c to: 3 char: a to: 4 char: b to: 5 char: c to: 6 char: b to: 7 char: b to: 8
3.zipWithIndex有序集合
当有序集合调用zipWithIndex的时候,它会返回一个有序的二元组集合,因为zipWithIndex是在一个已经存在的有序集合的基础上建立一个新的有序集合。
val list = List("a", "b", "c") list.zipWithIndex console: List[(String, Int)] = List((a,0), (b,1), (c,2))