Comments (7)
抛砖一个,模仿 kmp 滑动
function longestUniqueSubstr (str) {
str = String(str)
var index = {} // keys: char of a tentative substr, values: index
var tenLen = 0 // len of the tentative substr
var resLen = 0 // result len
for (let i = 0; i < str.length; i += 1) {
let ic = index[str[i]]
if (typeof ic !== 'undefined') {
if (tenLen > resLen) { resLen = tenLen }
i = ic + 1
index = {}
tenLen = 0
}
index[str[i]] = i
tenLen += 1
}
return Math.max(tenLen, resLen)
}
console.assert(longestUniqueSubstr('abcabcbb') === 3, 'abcabcbb')
console.assert(longestUniqueSubstr('bbbbb') === 1, 'bbbbb')
console.assert(longestUniqueSubstr('pwwkew') === 3, 'pwwkew')
console.assert(longestUniqueSubstr('') === 0, '')
console.assert(longestUniqueSubstr('1') === 1, '1')
console.assert(longestUniqueSubstr('111') === 1, '111')
console.assert(longestUniqueSubstr('1234') === 4, '1234')
console.assert(longestUniqueSubstr('11234') === 4, '11234')
console.assert(longestUniqueSubstr('12344') === 4, '12344')
console.assert(longestUniqueSubstr('1234445678') === 5, '1234445678')
console.assert(longestUniqueSubstr('1234235678') === 7, '1234235678')
from daily-algorithms.
我同意 @YabZhang 的算法, @crimx 的算法并非最优。
以 "abcabcbb" 为例,crimx 的算法 for 循环执行了 15 次,而 YabZhang 的 for 循环只执行了 8 次,YabZhang 的算法真正地做到了在任何情况下时间复杂度都是 O(n)。
crimx 的算法只有在某些情况才能达到 O(n),如"11234","2223445",也就是”相同的元素必须相邻“。
为什么会这样呢?我觉得问题在于 crimx 的算法中 i 指针进行了回溯,如下图所示。
举个例子:"abca",之前已经判断出 "abc" 是最大非重复子串。那么,再碰到第 4 位的相同元素 "a",因为第 4 位和第 1 为相同,1、2、3位构成最大非重复子串,那么2、3、4位自然也构成最大非重复子串。这个结论是可以直接推导出来的,不需要重复遍历 "bca" 才能知道。然而 crimx 的算法进行了这种冗余的遍历,我觉得这是 YabZhang 算法优于 crimx 算法的根本原因。
下面我把 YabZhang 的算法翻译成 JS 版本,以供测试。
function test(str) {
var index = {} // keys: char of a tentative substr, values: index
var tenLen = 0 // len of the tentative substr
var resLen = 0 // result len
for (let i = 0; i < str.length; i += 1) {
let ic = index[str[i]]
if (typeof ic !== 'undefined') {
if (tenLen > resLen) {
resLen = tenLen
}
tenLen = i - ic;
index[str[i]] = i;
} else {
tenLen += 1;
}
index[str[i]] = i
}
return Math.max(tenLen, resLen)
}
from daily-algorithms.
微博上看到的,抛个砖,希望能坚持下去.已经watch
function test(str) {
let map = {}
let currentLen = 0
let result = 0
for (let i = 0; i < str.length; i++) {
if (map[str[i]] === undefined) {
currentLen++
map[str[i]] = i
} else {
if (currentLen > result) {
result = currentLen
}
currentLen = 0
i = map[str[i]]
map = {}
}
}
return Math.max(currentLen, result)
}
写完之后才发现楼上的更好,更简洁,向楼上crimx
学习
from daily-algorithms.
console.assert(resolve('abbcdefdakngda') === 7);
function resolve(str) {
let maxLen = 0;
let map = {
length: 0
};
for(let i = 0, len = str.length; i < len; i++) {
if (map[str[i]]) {
maxLen = Math.max(map.length, maxLen);
i = map[str[i]] + 1;
map = {};
map.length = 0;
}
map[str[i]] = i;
map.length++;
}
return Math.max(map.length, maxLen);
}
写了一个,发现与 @crimx 的解法是一样的,应该还有更优解。
from daily-algorithms.
题目:找出一个字符串中最长的连续子串,输出这个子串的长度,要求:这个子串中没有重复的字符。
那么重点就在"没有重复字符"。
最简单的思路就是暴力遍历法,并在遍历的同时统计长度,找到重复字符就停止。最后给出最大的长度。
进一步优化的,可以使用hash表记录下来每个元素出现的索引值;
使用hash表记录,并在每次发现重复元素重新开始统计时,并从重复元素第一次出现的下一位继续算法;
进一步优化,重用建立的hash记录,每次发现重复元素时进行更新;
具体的思路就是用最新出现的元素索引覆盖之前出现的,并对当前的长度进行更新;
这样可以保证时间复杂度最坏:O(n),空间复杂度为:O(n)
代码如下:
def resolve(seq):
stat = {}
index = 0
max_len, tmp_len = 0, 0
while(index < len(seq)):
if seq[index] not in stat:
tmp_len += 1
else:
if tmp_len > max_len:
max_len = tmp_len
tmp_len = index - stat[seq[index]]
# update stat record
stat[seq[index]] = index
index += 1
return max(max_len, tmp_len)
assert resolve('abcabcbb') == 3
assert resolve('bbbb') == 1
assert resolve('pwwkew') == 3
assert resolve('1') == 1
assert resolve('111') == 1
assert resolve('112345678') == 8
from daily-algorithms.
@youngwind 确实记录每个字符最新的位置就不需要回溯了:thumbsup: 这样就保证了 i 到 ic 之间的字符必然是独立的。
from daily-algorithms.
@youngwind ,你算法有问题console.log(test('abccdefab')) 输出 7。计算速度1.4s
下面是我的笨方法,但是计算速度0.8s;
function longSubstr(str) {
var index ='';var length=0;var nstr=0;var longstr='';
for(var i = 0;i<str.length;i++){
if(index.indexOf(str[i])>-1){
index = '';
i=nstr;
nstr++;
} else {
index = index + str.charAt(i);
if(length<index.length){
length= index.length
longstr = index;
}
}
}
return {str: longstr, length: length}
}
from daily-algorithms.
Related Issues (16)
- Two Sum HOT 24
- Roman To Integer HOT 2
- 关于 daily-algorithms
- Longest Common Prefix HOT 2
- 3Sum HOT 14
- 3Sum Closest HOT 3
- Letter Combinations of a Phone Number HOT 4
- 4Sum HOT 4
- Reverse Integer HOT 8
- Add Two Numbers HOT 11
- Find The Longest Palindromic Substring HOT 8
- Regular Expression Matching HOT 3
- Palindrome Number HOT 3
- Container With Most Water HOT 3
- Integer to Roman HOT 6
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from daily-algorithms.