日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

野路子搞算法 · 讓算法可視化《leetcode03.無(wú)重復(fù)字符的最長(zhǎng)子串》

 小傅哥 2021-12-13

小傅哥 | https://
沉淀、分享、成長(zhǎng),專注于原創(chuàng)專題案例,以最易學(xué)習(xí)編程的方式分享知識(shí),讓自己和他人都能有所收獲。目前已完成的專題有;Netty4.x實(shí)戰(zhàn)專題案例、用Java實(shí)現(xiàn)JVM、基于JavaAgent的全鏈路監(jiān)控、手寫RPC框架、架構(gòu)設(shè)計(jì)專題案例、源碼分析、算法學(xué)習(xí)等。
你用劍🗡、我用刀🔪,好的代碼都很燒,望你不吝出招!

一、前言

在刷了第一道 leetcode 的題以后我一直在思考,怎么才能讓小白更清楚的了解到整個(gè)算法運(yùn)行的過(guò)程。如果只是單純的一點(diǎn)點(diǎn)看代碼,從中摸清楚整個(gè)流程確實(shí)還是有一些難度。雖然就一道題來(lái)說(shuō),代碼塊并不會(huì)很大,但僅憑借變量之間的交換以及斷點(diǎn)調(diào)試輸出結(jié)果,還是很難在我們的大腦中形成一個(gè)完整的執(zhí)行流程。

為此,最近經(jīng)過(guò)不斷的搜索在 Github 中找到了 MarkKoz 大神的算法可視化工程:algorithm-visualizer 。這是 nodejs 代碼,在按照文檔說(shuō)明安裝以及寫測(cè)試用例驗(yàn)證后,確實(shí)可以滿足目前的可視化需求。

好!那么我就按照自己的需求,將代碼部署到本地以及創(chuàng)建了一套符合自己需求可以將各種算法題進(jìn)行可視化展示。這套功能包括三部分,如下(可以下載后運(yùn)行);

序號(hào)名稱功能操作
1algorithm-visualizer可視化算法代碼平臺(tái),目前支持的算法包括回溯法、加密算法、動(dòng)態(tài)規(guī)劃、圖搜索、貪婪算法、搜索算法、排序算法等。下載
2server算法可視化服務(wù)器,用于編譯算法代碼提供服務(wù)接口。這個(gè)編譯過(guò)程會(huì)從 github 上下載算法代碼,并編譯到本地。下載
3algorithms算法代碼塊,這里面默認(rèn)包括了大量的可執(zhí)行展示的算法。同時(shí)在我們刷 leetcode 后也是將代碼編寫為可視化的方式,提交到這里。下載

效果展示:

  • 最左側(cè)是代碼區(qū)域,也就是我們提交到 algorithms中的算法代碼。不支持中文以及特殊符號(hào)
  • 中間是展示運(yùn)行過(guò)程區(qū)域,這部分主要來(lái)自于在算法代碼中添加的展示化代碼塊,例如:array1DTracer.select(beginIdx, i - 1);
  • 最右側(cè)是代碼區(qū)域,這里的代碼可以修改后構(gòu)建并運(yùn)行,但不會(huì)保存。同時(shí)在運(yùn)行的時(shí)候可以調(diào)整運(yùn)行速度 Speed,極大的方便了我們觀察算法的執(zhí)行過(guò)程
  • 上圖的展示內(nèi)容其實(shí)就是我們?cè)?leetcode 中做的第一題《兩數(shù)之和》其中的一中使用自己定義的 bit 結(jié)構(gòu)數(shù)組的方式求解的演示

那么!接下來(lái)我們開(kāi)始刷 leetcode中第三題《無(wú)重復(fù)字符的最長(zhǎng)子串》,并最終動(dòng)態(tài)展示給大家這段算法的執(zhí)行效果。如果你想在本地運(yùn)行,可以關(guān)注公眾號(hào):bugstack蟲(chóng)洞棧

二、題目:《無(wú)重復(fù)字符的最長(zhǎng)子串》

給定一個(gè)字符串,請(qǐng)你找出其中不含有重復(fù)字符的 最長(zhǎng)子串 的長(zhǎng)度。

示例 1:

輸入: "abcabcbb"
輸出: 3 
解釋: 因?yàn)闊o(wú)重復(fù)字符的最長(zhǎng)子串是 "abc",所以其長(zhǎng)度為 3。                   

示例 2:

輸入: "bbbbb"
輸出: 1
解釋: 因?yàn)闊o(wú)重復(fù)字符的最長(zhǎng)子串是 "b",所以其長(zhǎng)度為 1。

示例 3:

輸入: "pwwkew"
輸出: 3
解釋: 因?yàn)闊o(wú)重復(fù)字符的最長(zhǎng)子串是 "wke",所以其長(zhǎng)度為 3。
     請(qǐng)注意,你的答案必須是 子串 的長(zhǎng)度,"pwke" 是一個(gè)子序列,不是子串。

java

class Solution {
    public int lengthOfLongestSubstring(String s) {
       // TODO
    }
}

三、思路和實(shí)現(xiàn)

從題目和示例上可以分析到這個(gè)題主要是從字符串中順序?qū)ふ页鲆淮畠?nèi)部不重復(fù)又是整個(gè)字符串中最長(zhǎng)的那個(gè)字串。為了尋找到這樣的子串可能首先想到的是循環(huán)出所有子串的集合,之后選取最長(zhǎng)的。當(dāng)把整個(gè)思路在整理幾遍和簡(jiǎn)化后,那么是不就可以理解為,這是兩個(gè)值指針在字符串中往前跑,當(dāng)結(jié)尾指針碰到的元素與開(kāi)始指針指向的元素一致,則將開(kāi)始指針向前進(jìn)一位,之后繼續(xù)執(zhí)行直到結(jié)束算出最長(zhǎng)子串。整個(gè)思路可以用下圖展示;

  • 從上圖的算法可以看到,只要先跑的那個(gè)指針也就是子串結(jié)尾的指針,碰到了開(kāi)始指針中間,一樣的元素,就將指針位置指向相同元素的下一位。切記不是指針 +1
  • 為了實(shí)現(xiàn)這樣的功能,我們就需要存儲(chǔ)兩個(gè)指針,同時(shí)需要有方法判斷元素所處的位置。那么有如下幾個(gè)方法;
    • 使用 indexOf,整個(gè)方法可以判斷元素位置,同時(shí)可以指定從某個(gè)位置開(kāi)始判斷后面的元素是否存在相同元素。
    • 使用 toCharArray(),轉(zhuǎn)換為數(shù)組,并將元素按照按照編碼位置存放到新建的數(shù)組中,用于判斷元素是否出現(xiàn)過(guò)。
    • 使用 bit,建立一個(gè)數(shù)組結(jié)構(gòu),通過(guò)與運(yùn)算獲取元素位置,并存放。方便快速查找。
  • 另外在比對(duì)是否撞上相同元素的時(shí)候,可以輸出當(dāng)前開(kāi)始指針與結(jié)束指針中間的長(zhǎng)度,并與之前的記錄的值比對(duì),如果超過(guò)則更新,直到最后輸出。

1. 實(shí)現(xiàn)方式,indexOf

public int lengthOfLongestSubstring_1(String s) {
    if (null == s || "".equals(s)) return 0;
    if (" ".equals(s) || s.length() == 1) return 1;  

    int beginIdx = 0, endIdx = 0, maxSize = 0;
    for (int i = 1; i  s.length(); i++) {
        endIdx = i;
        int existIdx = s.indexOf(s.charAt(i), beginIdx);
        if (existIdx  endIdx) {
            beginIdx = existIdx + 1;
        }
        int eval = endIdx - beginIdx + 1;
        if (maxSize  eval) {
            maxSize = eval;
        }
    }
    return maxSize;
}
  • 不滿足條件的字符串直接按照規(guī)則返回。
  • 每次循環(huán)計(jì)算是否碰撞到相同的元素,并處理開(kāi)始指針的位置。
  • 最后輸出最長(zhǎng)子串的長(zhǎng)度。

2. 實(shí)現(xiàn)方式,toCharArry

public int lengthOfLongestSubstring_2(String s) {
    if (null == s || "".equals(s)) return 0;
    if (" ".equals(s) || s.length() == 1) return 1;    

    char[] array = s.toCharArray();
    int[] exist = new int[127];
    exist[array[0]] = 1;     

    int beginIdx = 1, endIdx = 1, maxSize = 0;
    for (int i = 1; i  array.length; i++) {
        endIdx = i;
        if (exist[array[i]] >= beginIdx) {
            maxSize = Math.max(i - beginIdx + 1, maxSize);
            beginIdx = exist[array[i]] + 1;
        }
        exist[array[i]] = i + 1;
    }
    maxSize = Math.max(exist[array[endIdx]] - beginIdx + 1, maxSize);
    return maxSize;
}
  • 同樣不滿足的字符串直接返回。
  • 字符串轉(zhuǎn)換為數(shù)組,同時(shí)定義一個(gè)新的數(shù)組用于存放地址。int[] exist = new int[127],元素作為地址,位置作為值。
  • 只有在碰撞時(shí)候才計(jì)算兩個(gè)指針間的長(zhǎng)度,其他時(shí)間不計(jì)算。
  • 最后輸出最長(zhǎng)子串的長(zhǎng)度。

3. 實(shí)現(xiàn)方式,bit結(jié)構(gòu)

public int lengthOfLongestSubstring_3(String s) {
    if (null == s || "".equals(s)) return 0;
    if (" ".equals(s) || s.length() == 1) return 1;    

    int volume = 128;
    int bitMode = volume - 1;
    int[] t = new int[volume];
    int beginIdx = s.charAt(0) & bitMode, endIdx = 0, maxSize = 0;
    t[beginIdx] = 1;
    for (int i = 1; i  s.length(); i++) {
        endIdx = s.charAt(i) & bitMode;
        int val = t[endIdx];
        if (val != 0 && val >= t[beginIdx]) {
            beginIdx = s.charAt(val) & bitMode;
            t[beginIdx] = val + 1;
        }
        t[endIdx] = i + 1;
        int v = t[endIdx] - t[beginIdx] + 1;
        if (v > maxSize) {
            maxSize = v;
        }
    }
    return maxSize;
}
  • 如果你把上面的代碼看明白了,那么這塊的邏輯變化只是在于將元素通過(guò)運(yùn)算存放到bit結(jié)構(gòu)中,這和我們?cè)谟?jì)算《兩數(shù)之和》的算法方式一樣。

四、算法可視化運(yùn)行

  • 通過(guò)可視化運(yùn)行可以很方便的看到算法的執(zhí)行過(guò)程,這要比我們只是用腦子一遍遍過(guò)程流程清晰的多。尤其是對(duì)新人來(lái)說(shuō),簡(jiǎn)直太方便了。
  • 這個(gè)可視化運(yùn)行的工具,可以自己下載安裝,他是nodejs的環(huán)境。如果在使用過(guò)程中遇到什么問(wèn)題,可以關(guān)注公眾號(hào)(bugstack蟲(chóng)洞棧)內(nèi)聯(lián)系我。

五、總結(jié)

  • 想做好算法目前看到最主要的是捋清楚它的執(zhí)行思路,之后選擇不同的數(shù)據(jù)結(jié)構(gòu)進(jìn)行填充數(shù)據(jù)。最后按照這個(gè)流程一點(diǎn)點(diǎn)調(diào)試算法,以滿足所有情況。
  • 在可視化工具的輔助下,可以更加輕松的看到算法內(nèi)部的執(zhí)行過(guò)程。并且將算法轉(zhuǎn)換為可視化,也不是很復(fù)雜,只要按照標(biāo)準(zhǔn)編寫即可。
  • 如果你也是一個(gè)愛(ài)做算法題的小白或者大牛,也歡迎你加入我們的算法可視化中,讓我們一起開(kāi)始算法之旅:https://github.com/niubility-algorithm

    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多