劍指offer js演算法練習(1-10)

来源:https://www.cnblogs.com/yujinhongmm/archive/2019/03/26/10601249.html
-Advertisement-
Play Games

1.二維數組中的查找 在一個二維數組中(每個一維數組的長度相同),每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個函數,輸入這樣的一個二維數組和一個整數,判斷數組中是否含有該整數。 時間限制:1秒 空間限制:32768K 分析:由於每一行都按照從左到右遞增的順序排序 ...


1.二維數組中的查找
       在一個二維數組中(每個一維數組的長度相同),每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個函數,輸入這樣的一個二維數組和一個整數,判斷數組中是否含有該整數。

       時間限制:1秒 空間限制:32768K

分析:由於每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序,所以右上角的數字就是該行的最大值,該列的最小值。則可以通過把目標數與右上角的數字比較來判斷其位置,如果目標數比該數字小,由該數字為該列的最小值可得這一列都不會有目標數,我們就可以將該列刪除,並得到新的二維數組,再次比較目標數與右上角的數字的大小關係。如果目標數比該數字大,由該數字為該行的最大值可得這一行都不會有目標數,我們就可以將該行刪除,並得到新的二維數組,再次比較目標數與右上角的數字的大小關係。如果目標數與右上角的數字相等,則返回true,找到了該目標數。如果當行數和列數都被刪完了還沒找到,則該二維數組中就沒有該目標數。

function Find(target, array)
{
    if(array==undefined||array.length<0||array[0].length<0){
        return false;
    }
    let rows=array.length;
    let columns=array[0].length;
    let row=0;
    let column=columns-1;
    while(row<rows&&column>=0){
        if(array[row][column]==target){
            return true;
        }
        if(array[row][column]>target){
            column--;
        }else{
            row++;
        }
    }
    return false;
}

2.替換空格
        請實現一個函數,將一個字元串中的每個空格替換成“%20”。例如,當字元串為We Are Happy.則經過替換之後的字元串為We%20Are%20Happy。

       時間限制:1秒 空間限制:32768K

分析:這裡用replace+正則表達式即可替換。

function replaceSpace(str)
{
    return str.replace(/ /g,'%20')
}

3.從頭到尾列印鏈表
       輸入一個鏈表,按鏈表值從尾到頭的順序返回一個ArrayList。鏈表節點如下:

function ListNode(x){
    this.val = x;
    this.next = null;
}

       時間限制:1秒 空間限制:32768K 

分析:首先我們應該判斷鏈表是否存在,如果鏈表存在的話,就用一個迴圈來判斷節點是否存在,依次將節點中的值放入棧(題目要求從尾到頭的順序)即可。

function printListFromTailToHead(head)
{
    if(head==undefined)
    {
        return 0;
    }else
    {
        var arr=new Array();
        var curr=head;
        while(curr)
        {
            arr.push(curr.val);
            curr=curr.next;
        }
        return arr.reverse();
    }
}


4.重建二叉樹
       輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重覆的數字。例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6},則重建二叉樹並返回。樹節點如下:

function TreeNode(x) {
    this.val = x;
    this.left = null;
    this.right = null;
} 


       時間限制:1秒 空間限制:32768K 

分析:首先我們要知道前序遍歷的順序是根左右,中序遍歷的順序是左根右。前遍歷的第一個數總是根,所以我們就可以在前序遍歷中先找到根,再在中序遍歷中分別找到左子樹和右子樹,然後再分別在左子樹和右子樹中按照相同的方法去找它們的根節點,左右子樹,直到在某個子樹中的前序和後序遍歷的長度都為0。由此我們可以寫出如下的遞歸代碼:

function reConstructBinaryTree(pre, vin)
{
    if(pre.length==0&&vin.length==0)
    {
        return null;
    }
    var index=vin.indexOf(pre[0]);
    var left=vin.slice(0,index);
    var right=vin.slice(index+1);
    var root=new TreeNode(pre[0]);
    root.left=reConstructBinaryTree(pre.slice(1,index+1),left);
    root.right=reConstructBinaryTree(pre.slice(index+1),right);
    return root;
}


5.用兩個棧實現隊列
       用兩個棧來實現一個隊列,完成隊列的Push和Pop操作。 隊列中的元素為int類型。

       時間限制:1秒 空間限制:32768K 

分析:首先我們要明白棧的特點是後進先出,隊列的特點是先進先出。這裡我們可以用棧stack1壓入隊列,不做特殊處理,就用棧的方法壓入。再在另一個用於Pop的方法中,把stack1中數依次彈出並壓入棧stack2,這樣就滿足了最先進入棧stack1在棧stack2的棧頂,由於Pop操作每次只彈出一個值,所以需要彈出stack2的棧頂值,用一個變數存起來,然後再把stack2中數依次彈出並壓入棧stack1,以便下次正常壓入彈出,最後返回變數即可。

var stack1=new Array();
var stack2=new Array();
 
function push(node)
{
    stack1.push(node);
}
function pop()
{
    var temp=stack1.pop();
    while(temp){
        stack2.push(temp);
        temp=stack1.pop();
    }
    var result=stack2.pop();
    temp=stack2.pop();
    while(temp){
        stack1.push(temp);
        temp=stack2.pop();
    }
    return result;
}

6.旋轉數組的最小數字
        把一個數組最開始的若幹個元素搬到數組的末尾,我們稱之為數組的旋轉。 輸入一個非減排序的數組的一個旋轉,輸出旋轉數組的最小元素。 例如數組{3,4,5,1,2}為{1,2,3,4,5}的一個旋轉,該數組的最小值為1。 NOTE:給出的所有元素都大於0,若數組大小為0,請返回0。

        時間限制:3秒 空間限制:32768K

分析:這道題可以用二分法來做,但是會出現超時,所以用js的Math.min.apply(null,arr)方法來求是最高效的。

function minNumberInRotateArray(rotateArray)
{
    if(rotateArray.length==0){
        return 0;
    }
    return Math.min.apply(null,rotateArray);
}


7.斐波那契數列
        大家都知道斐波那契數列,現在要求輸入一個整數n,請你輸出斐波那契數列的第n項(從0開始,第0項為0)。n<=39

        時間限制:1秒 空間限制:32768K

分析:斐波那契數列指的是這樣一個數列 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,610,987,1597,2584,4181,6765,10946,17711,28657,46368........這個數列從第3項開始,每一項都等於前兩項之和。解決斐波那契數列可以使用遞歸的解法,但是這個卻不是最優解,因為遞歸會產生很多重覆的計算。為避免重覆計算,我們可以根據f(0)和f(1)算出f(2),再根據f(1)和f(2)算出f(3)......依次類推就可以算出第n項了。

function Fibonacci(n){
    if(n<0||n>39){
        return;
    }
    if(n==0){
        return 0;
    }
    if(n==1){
        return 1;
    }
    var fibNMinusOne=0;
    var fibNMinusTwo=1;
    var fibN=0;
    for(var i=2;i<=n;i++){
        fibN=fibNMinusOne+fibNMinusTwo;
        fibNMinusOne=fibNMinusTwo;
        fibNMinusTwo=fibN;
    }
    return fibN;
}


8.跳臺階
        一隻青蛙一次可以跳上1級臺階,也可以跳上2級。求該青蛙跳上一個n級的臺階總共有多少種跳法(先後次序不同算不同的結果)。

        時間限制:1秒 空間限制:32768K

分析:首先我們考慮最簡單的情況。如果只有1級臺階,那顯然只有一種跳法。如果有2級臺階,那就有兩種跳法:一種是分兩次跳,每次跳1級;另一種就是一次跳2級。接著我們再來討論一般情況。我們把n級臺階時的跳法看成n的函數,記為f(n)。當n>2時,第一次跳的時候就有兩種不同的選擇:一次第一次只跳1級,此時跳法數目等於後面剩下的n-1級臺階的跳法數目,即為f(n-1);二是第一次跳2級,此時跳法數目等於後面剩下的n-2級臺階的跳法數目,即為f(n-2)。因此,n級臺階的不同跳法的總數f(n)=f(n-1)+f(n-2)。這實際上就是斐波那契數列。

function jumpFloor(number){
    if(number <= 0){
        return 0;
    }
    if(number == 1){
        return 1;
    }
    if(number == 2){
         return 2;
    }
    var jumpNMinusOne=1;
    var jumpNMinusTwo=2;
    var jumpN=0;
    for(var i=3;i<=number;i++){
        jumpN=jumpNMinusOne+jumpNMinusTwo;
        jumpNMinusOne=jumpNMinusTwo;
        jumpNMinusTwo=jumpN;
    }
    return jumpN;
}


9.變態跳臺階
        一隻青蛙一次可以跳上1級臺階,也可以跳上2級……它也可以跳上n級。求該青蛙跳上一個n級的臺階總共有多少種跳法。

        時間限制:1秒 空間限制:32768K​​​​​​​

分析:首先我們考慮最簡單的情況。如果只有1級臺階,那顯然只有一種跳法。如果有2級臺階,那就有兩種跳法:一種是分兩次跳,每次跳1級;另一種就是一次跳2級。如果只有3級臺階,那就有4種跳法:①分三次跳,每次跳1級;②分二次跳,第一次跳2級第二次跳1級;③分二次跳,第一次跳1級第二次跳2級;④分一次跳,直接跳3級。接著我們再來討論一般情況。我們把n級臺階時的跳法看成n的函數,記為f(n)。當n>1時,第一次跳的時候就有n種不同的選擇:第一次只跳1級,此時跳法數目等於後面剩下的n-1級臺階的跳法數目,即為f(n-1);第一次跳2級,此時跳法數目等於後面剩下的n-2級臺階的跳法數目,即為f(n-2);同理第一次跳n-1級,此時跳法數目等於後面剩下的1級臺階的跳法數目,即為f(1);第一次跳n級,此時跳法數目等於後面剩下的0級臺階的跳法數目,即為f(0)也就是0次。因此,n級臺階的不同跳法的總數f(n)=f(n-1)+f(n-2)+...+f(0)。又因f(n-1)=f(n-2)+f(n-3)+...+f(0)。所以f(n)=2*f(n-1)。

function jumpFloorII(number)
{
    if(number <= 0){
        return 0;
    }
    if(number == 1){
        return 1;
    }
    var jumpNMinus=1;
    var jumpN=0;
    for(var i=2;i<=number;i++){
        jumpN=jumpNMinus*2;
        jumpNMinus=jumpN;
    }
    return jumpN;
}

10.矩形覆蓋
        我們可以用2*1的小矩形橫著或者豎著去覆蓋更大的矩形。請問用n個2*1的小矩形無重疊地覆蓋一個2*n的大矩形,總共有多少種方法?​​​​​​​

        時間限制:1秒 空間限制:32768K​​​​​​​

分析:

             

             

 

        我們討論一般情況。我們把放的方法的看成n的函數,記為f(n)。當第一個小矩形這樣橫著放時,剩下的放法即為f(n-2)。

            

 

        當第一個小矩形這樣豎著放時,剩下的放法即為f(n-1)。由此我們可以得到f(n)=f(n-1)+f(n-2),所以這個問題其實還是斐波那契數列。

function rectCover(number)
{
    if(number==1){
        return 1;
    }
    if(number==2){
        return 2;
    }
    var rectNMinusOne=1;
    var rectNMinusTwo=2;
    var rectN=0;
    for(var i=3;i<=number;i++){
        rectN=rectNMinusOne+rectNMinusTwo;
        rectNMinusOne=rectNMinusTwo;
        rectNMinusTwo=rectN;
    }
    return rectN;
}

 




您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、問題描述 問題是這樣的,後臺傳了xArr = [x1, x2,...,xn]和yArr = [y1, y2, ..yn]兩個數組,前端要渲染出表格並且可以填寫每個單元格的值,然後按照一定數據結構保存並傳給後臺,並且再次獲取這個數據結構和數組xArr、yArr可以自己渲染出這個表?實現新增和修改的 ...
  • usually.js 是一個面向現代 Web 開發的 JavaScript 函數庫,基於 ES6 開發。最新版本2.4.1,最新版本usually.js增加管道函數—— pipe 函數。什麼是管道函數?管道函數,其作用是將前一步的結果直接傳參給下一步的函數,從而省略了中間的賦值步驟,可以大量減少記憶體... ...
  • 一、快捷位置和尺寸屬性 DOM已經提供給我們計算後的樣式,但是還是覺得不方便,因為計算後的樣式屬性值都是字元串類型。 不能直接參与運算。 所以DOM又提供了一些API:得到的就是number類型的數據,不需要parseInt(),直接可以參與運算。 offsetLeft和offsetTop offs ...
  • 一、單例模式: 所謂單例模式,即保證一個類只有一個實例,並提供一個訪問它的全局訪問點。 單例模式實現彈出層: 二、觀察者模式: 所謂觀察者模式,即(發佈-訂閱模式):其定義對象間一種一對多的依賴關係,當一個對象的狀態發生改變時,所有依賴於它的對象都將得到通知。 觀察者模式常見面試題: 三、組合模式: ...
  • Layui 分為單頁版和iframe版 單頁版 通過將單頁代碼輸出到div,不如要完整的html代碼。 刷新頁面後,依然能夠記錄上一次的頁面。 此種方式不易於調試前端代碼。 Iframe版 通過iframe的方式將載入另一個頁面。需要完整的html代碼,包括js代碼。 屬性頁面後,不能夠記錄上一次的 ...
  • 在學習表格時我們會遇到一些既跨行又跨列合併的情況,此時可以用下麵這種方法來實現。 但是需要特別指出的是,如果一個單元格既跨行又跨列合併了,那麼最好不要再讓相鄰單元格也跨行或跨列合併了。 此時會出現如下所示的錯誤效果,可以看到單元格與單元格的尺寸不再一致了。 ...
  • 大家好 !! 又見面了, 今天我們來搞一搞 H5的新增API FileReader 真是一個超級超級方便的API呢!!!很多場景都可以使用.......... 我們先不贅述MDN文檔里的內容, 我們從 1 到 0, 從 一個 小Demo 入手 開始 瞭解 它; 請開始你的表演: 是不是簡單又炫酷, ...
  • 一、獲取元素方法(JS選擇器) 1.1概述 得到id元素的方法 document.getElementById() 得到一個元素。事實上,還有一個方法可以得到標簽元素,並且得到的是多個元素: document.getElementsByTagName(); 全線瀏覽器相容的,得到元素的方法,就這兩個 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...