1. 程式人生 > >LeetCode 方法詳解

LeetCode 方法詳解

1:兩個數的和為一個定值 題目描述:給一個序列,找到兩個數的和為給定的值,返回這兩個數的索引。 題目解析: (1)暴力法:i從0...n-1;j從i+1...n。如果兩個數的和等於給定值,就返回索引。時間複雜度高O(n^2) (2)排序+掃描:將陣列排序,然後i指標後移,j指標左移,直到找到兩個數的和等於給定值。時間複雜度O(n logn) (3)空間換時間:a+b = target。也就是在陣列中找target - a。先將陣列掃描一遍,建立一個hash表,然後再掃描陣列,判斷target-arr[i]是否在hash表中。 時間複雜度O(n)。 2:找到兩個有序陣列的中間值,但時間複雜度要是O(log(m+n)) 題目解析: (1)暴力法,但不滿足題意 (2)二分查詢+遞迴:比如A[m]和B[n]陣列。我們找第k大的數的時候,就用A[k/2-1]和B[k/2-1]比較,如果是小於號,證明A的前k/2的資料都在合併後的陣列的前半區。然後遞迴進行處理! 3、找出最長不連續的子串 題目描述:"abcabcbb"中"abc"最長。 題目解析:可以理解成一個滑動視窗,滑動視窗內的字元不重複,求最大的視窗大小。 (1)暴力法:以每一個字元為起點,向右遍歷,找到最大的長度。 (2)雜湊表:我們用一個26個字元的陣列來表示該字元是否出現過。但這就帶來了一個問題,abcbdef,當遍歷到第2個b的時候,a資料應該清除掉的。那麼這個時候,我們就用兩個指標,i慢,j快。當發現重複的時候,就i++並且清楚hash表的相應位。 (3)雜湊表:我們可以用26個字元的陣列來儲存該字元的位置。當發現重複的時候,就要將位置賦值成新的位置,但是其他位置要如何修改?由於len增加的時候是一個一個增加,而減小的時候,可以大幅度一次性減小。可以利用len = min(len+1,j-index)來推測新值。 4、兩個連結串列相加 題目描述:將一個數的每一位用連結串列的形式儲存,現在要將兩個數相加,求得最後的結果。 題目解析:就是簡單相應的位相加,要注意進位。L1->data 、L2->data和carryover三個數相加,分兩次執行,這樣就不用同時滿足L1和L2都不為空。簡化程式碼的實現。 5、最長迴文子串 題目解析: (1)暴力法:起始位置為i,讓j從i+1到n遍歷,針對每一個j判斷i--j是否是迴文字串。O(n^3) (2)動態規劃:p[i,j] = (s[i] == s[j]) && p[i+1,j-1]; (3)中心擴充套件法:以每一個字元為中心,向兩邊擴充套件。注意要分奇偶擴充套件。 (4)Manacher演算法:O(n) 6、鋸齒形轉換 題目解析: (1)通過數學分析找出規律,每行都有哪些元素座標。 (2)用c++的容器,可以新增元素,就不用專門設陣列。按照上下遍歷即可。 7、翻轉整數 題目描述:將123變化成321,-123變化成-321 題目解析: 轉換的思路倒不難,但是關於儲存資料的方式一定要整理清楚: (1)unsigned int temp = (unsigned int)n;必須要強制型別轉換。 (2)輸出資料的時候要用%u來輸出無符號資料 (3)對於一個整數每一位進行描述,我們要麼轉化成字串進行處理,要麼通過陣列來表示 8、迴文數字 題目解析: (1)我們可以判斷最高位和判斷最低位是否相等,若相等,則去掉高位和去掉低位,剩餘的資料再判斷是不是迴文數 (2)可以利用翻轉來解決,當然這裡要注意溢位的問題,不過我們可以用longlong型別,定義更大的資料,然後reverse = 10*reverse+curNum%10;   curNum /= 10; 最後,判斷reverse == curNum。 (3)將整數轉換成字串或者陣列來表示,然後用前後指標來判斷是否相等。 (4)通過《左旋轉字串》得到啟發,我們可以將"54322345"拆分成"5432"和"2345",然後將其中一個翻轉,判斷兩個數是否相等。 9、裝最多的水 題目描述:arr[n]的陣列中,第i個位置的線的高度為arr[i],任取兩條線,求能裝的最大容量。 題目解析: (1)暴力方法:分別以每條線為起點,求得最大的容量。 (2)兩個指標:i...j。求得體積後,小的邊向多方移動一位,求面積更新。 (3)優化方案二:i....j。求得體積後,讓小的邊向對方移動,直到找到比它大的邊停止,求值更新;再移動小的邊…… 10:整數轉換為羅馬數字 題目解析: 對於一個整數,我們需要從高位向低位一點一點轉換,由於羅馬數字是有對應關係的,我們通過陣列來表示即可。
  1.     int
     value[] = {1000,900,500,400,100,90,50,40,10,9,5,4,1};  
  2.     char *roman[] = {"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"};  
  3.     char store[20] = {0};  
  4.     int len = sizeof(value)/sizeof(int);  
  5.     for(int i = 0;i < len;++i){  
  6.         while(n >= value[i]){  
  7.             n -= value[i];  
  8.             strcat(store,roman[i]);  
  9.         }  
  10.     }  
11、羅馬數字轉換成整數 題目解析: 這裡求解的時候要從羅馬數字的低位向高位移動,碰到相應的字母就轉換成相應的數字。但對於"IX"我們有10-1=9。也就是當str[i] < str[i+1]時,減去str[i]表示的數字。
  1.     arr['I'-'A'] = 1;  
  2.     arr['V'-'A'] = 5;  
  3.     arr['X'-'A'] = 10;  
  4.     arr['L'-'A'] = 50;  
  5.     arr['C'-'A'] = 100;  
  6.     arr['D'-'A'] = 500;  
  7.     arr['M'-'A'] = 1000;  
  8.     result = arr[str[n-1]-'A'];  
  9.     for(int i = n-2;i >= 0;--i){  
  10.         if(arr[str[i]-'A'] >= arr[str[i+1]-'A'])  
  11.             result = result + arr[str[i]-'A'];  
  12.         else
  13.             result = result - arr[str[i]-'A'];  
  14.     }  
12、最長公共字首 一系列字串中,兩兩比較,找到最短的字首。 13、號碼的字串組合 題目解析: 深度優先遍歷的典型引用。對於每一個字元所代表的數字遍歷,然後遞迴到下一個字元。 注意區別什麼時候當前遞迴函式中需要加for迴圈,什麼時候不需要加。當前字元有多重可能的時候,就for迴圈表示。 14、移除連結串列中倒數第n個結點 題目解析: 很簡單,但要注意輸入引數的判斷、連結串列個數以及臨界條件。 15、括號匹配 題目解析: 給定一個由左右括號組成的字串,判斷是否是匹配的。通過一個棧來實現,左括號就入棧,右括號時與出棧元素向匹配。 當然當匹配到最後的時候,還要判斷棧是否為空,如果不為空也是匹配失敗。 16、生成括號 題目解析: (1)深度優先演算法: 利用標記陣列來標記哪些還沒訪問過。找到第一個沒有被訪問的位置i,然後在i+1,i+3,i+4....位置放置右括號。但是要注意,如果在j放了右括號後,j+1已經右括號了,就不再向右判斷了!否則會出現重複的現象。 當退出當前迴圈的時候,第i的位置要清零。
  1. void DFS(int *visited,char *buf,int n)  
  2. {  
  3.     int i;  
  4.     for(i = 0;i < n;i++){  
  5.         if(visited[i] == 0)  
  6.             break;  
  7.     }  
  8.     if(i == n){  
  9.         puts(buf);  
  10.         return;  
  11.     }  
  12.     visited[i] = 1;  
  13.     buf[i] = '(';  
  14.     for(int j = i+1;j < n;j+=2){  
  15.         visited[j] = 1;  
  16.         buf[j] = ')';  
  17.         DFS(visited,buf,n);  
  18.         visited[j] = 0; //清除標誌
  19.         if(visited[j+1] == 1)   //已經到達邊界
  20.             break;  
  21.     }  
  22.     visited[i] = 0;<span style="white-space:pre"> </span>//清楚標誌
  23. }
(2)卡特蘭級數 可以利用括號個數的特性,在任何時刻,left <=right。也就是不能先放右括號再放左括號。 所有對於第i個位置,如果left>0就能放')',如果left<right,就能放'('。這也就是變相的0,1選擇問題。
  1. void generate(int leftNum,int rightNum,string s,vector<string> &result)  
  2.     {  
  3.         if(leftNum==0&&rightNum==0)  
  4.         {  
  5.             result.push_back(s);  
  6.         }  
  7.         if(leftNum>0)  
  8.         {  
  9.             generate(leftNum-1,rightNum,s+'(',result);  
  10.         }  
  11.         if(rightNum>0&&leftNum<rightNum)  
  12.         {  
  13.             generate(leftNum,rightNum-1,s+')',result);  
  14.         }  
  15. }  
擴充套件: 對於一個數組,打印出所有的入棧出棧序列。 17、合併k個連結串列 題目解析: (1)一個一個合併,時間複雜度為2n+3n+....kn = O(n*k*k); (2)兩兩歸併。我們可以用遞迴或者迴圈。for(int i = 0;i + half < size;i++) 時間複雜度O(nklogk),空間複雜度的話是遞迴棧的大小O(logk)。  (3)用堆進行排序:使用priority_queue,這個容器是用堆實現的,不過預設構建的是大頂堆,彈出最大值後,將該最大值後面的結點入佇列。 18、將連結串列中的元素兩兩交換 很簡單,設定三個指標即可,但要注意null,一個結點,兩個結點等情況。 19、從有序陣列中移除重複的資料 通過快排的第二種方法受到啟發,設定兩個指標變數i,j當不重複的時候,就將該資料放到i+1的位置,然後移動索引變數。 20、刪除指定元素 題目描述:從陣列中刪除指定的key元素。 題目解析: (1)可以利用上一題的方法,i,j都從前向後移動,當j指向的不是key的時候,就向i賦值。 (2)也可以變通一下,i從左向右,j從右向左。當i移動到指向key的位置停止,j從右向左移動到不是key的位置,然後將該元素賦值給i位置。 21、在有序陣列中找到插入位置 題目解析: (1)順序查詢 (2)二分查詢:凡是碰到有序陣列,並且讓查詢的,一般都要考慮用二分查詢方式 22、查詢資料出現的範圍 題目描述:[1,2,3,4,4,5]找資料4,返回[3,4]。 題目解析: 這道題是二分查詢的加強版,二分查詢的時候,當發現要查詢的值的時候就立即退出,但這裡是找範圍,所有判斷條件有所變化。 分兩次二分查詢,一次查詢左邊界,一次查詢右邊界: (1)找左邊界:arr[mid] >= key;hi = mid-1; 退出迴圈時,lo為左邊界 (2)找右邊界:arr[mid] <= key; lo = lo+1; 退出迴圈時,hi為右邊界 23、下一個排列 題目描述:2543--->3245 題目解析: 通過分析陣列的形式,我們從後向前掃描直到找到第一對a[i]<a[i+1]的位置,然後將第i個元素和從後向前遍歷的第一個最大的交換,然後將i後面的資料翻轉。比如:23876654433-----(1)24876654333--------(2)24333456678 就得到了我們想要的結果。當然如果整個資料都是逆序的,那麼就將整個陣列翻轉,輸出最小的數即可。 24、最長有效的括號匹配 題目描述:")()())" 返回 "()()" -----4 題目解析: 這裡用棧來解決,但是棧中儲存的不再是左右括號了,而是儲存的是左括號的座標位置,當碰到左括號就入棧,碰到右括號就出棧一個,並計算長度!比如((()),得到第二個右括號時為4-0。 有個小問題要解決:當棧退完時,就不能計算當前的長度了!比如棧從棧底到棧頂為2 3 4(1和0是一對括號已經退出),那麼連續三個括號後已經退出了所有的元素,就不知道改真名計算有效的字串長度了。不能簡單的認為減去(2-1)。 解決方法是,先向棧中放一個標記-1。當在程式執行過程中,棧中只剩下一個元素了,並且還要出棧!(也就是碰到了右括號),就將-1彈出,並放入該右括號的座標,代表這個右括號是不匹配的。
  1.         stack<int> S;  
  2.         S.push(-1);  
  3.         for(int i = 0;i < n;i++){  
  4.             if(str[i] == '('){  

    相關推薦

    LeetCode 方法

    1:兩個數的和為一個定值 題目描述:給一個序列,找到兩個數的和為給定的值,返回這兩個數的索引。 題目解析: (1)暴力法:i從0...n-1;j從i+1...n。如果兩個數的和等於給定值,就返回索引。時間複雜度高O(n^2) (2)排序+掃描:將陣列排序,然後i指標後移,j指標左移,直到找到兩

    $.ajax()方法

    例如 lencod ace 包含 等等 json 返回 用戶名 代碼 jquery中的ajax方法參數總是記不住,這裏記錄一下。 1.url: 要求為String類型的參數,(默認為當前頁地址)發送請求的地址。 2.type: 要求為String類型的參數,請求方式(p

    Python的反射機制、hasattr() getattr() setattr() 函數使用方法

    對象 tee lin sel __main__ err ace traceback 一個 hasattr(object, name)判斷一個對象裏面是否有name屬性或者name方法,返回BOOL值,有name特性返回True, 否則返回False。需要註意的是name要用

    php上傳文件大小限制的方法

    mem 限制 upload 文件夾 tro 最大 指定 php上傳文件 配置 打開php.ini,首先找到file_uploads = on ;是否允許通過HTTP上傳文件的開關。默認為ON即是開upload_tmp_dir ;文件上傳至服務器上存儲臨時文件的地方,如果沒指

    接口測試工具soapUI的安裝和使用方法

    service 技術 key custom media 負載 bmp file text soapUI是一個開源測試工具,通過soap/http來檢查、調用、實現Web Service的功能/負載/符合性測試。 使用soapUI可以非常方便的實現接口的功能測試、穩

    Arrays 類的 binarySearch() 數組查詢方法

    strong object tro search mage bject 技術分享 eight 獲得 Arrays類的binarySearch()方法,可以使用二分搜索法來搜索指定的數組,以獲得指定對象。該方法返回要搜索元素的索引值。binarySearch()方法提供多種重

    JavaScript中getBoundingClientRect()方法

    script otto java chrome 頁面 支持 urn client fire getBoundingClientRect() 這個方法返回一個矩形對象,包含四個屬性:left、top、right和bottom。分別表示元素各邊與頁面上邊和左邊的距離。

    C# Process.Start()方法

    stat 字符串 檔案 atd 一個 用戶名 菜單 簡單介紹 run System.Diagnostics.Process.Start(); 能做什麽呢?它主要有以下幾個功能: 1、打開某個鏈接網址(彈窗)。 2、定位打開某個文件目錄。 3、打開系統特殊文件夾,如“控制面板

    HTML中javascript的<script>標簽使用方法

    mime類型 jsp source 方式 clas 處理 網頁 鏈接 屬性。 原文地址:HTML中javascript的<script>標簽使用方法詳解 只要一提到把JavaScript放到網頁中,就不得不涉及Web的核心語言——HTML。在當初開發javasc

    解析xml的4種方法(轉)

    項目 目標 源碼 更多 news 大量 優秀 大型 頻繁 http://blog.csdn.net/jzhf2012/article/details/8532873 1. 介紹 1)DOM(JAXP Crimson解析器) DOM是用與平臺和語言無關的方式表

    php中二維數組排序問題方法

    ges cti cmp each ace esc 對數 x11 用法 PHP中二維數組排序,可以使用PHP內置函數uasort() 示例一: 使用用戶自定義的比較函數對數組中的值進行排序並保持索引關聯 回調函數如下:註意回調函數的返回值是負數或者是false的時候,表

    SylixOS 調試方法——靜態代碼分析

    sylixos 調試方法1. SylixOS調試方法介紹SylixOS 實現了一個功能強大的調試 stub,可在設備或模擬器上在線調試應用程序,RealEvo-IDE 也提供配套的調試插件。目前 RealEvo-IDE 既支持自動推送調試、也支持傳統的手動啟動 gdbserver 的調試方式。在官方公布的使用

    python魔法方法

    返回 call __init__ and -m 描述 nbsp shift 賦值 文章來源:http://blog.csdn.net/koko66/article/details/42709279 據說,Python 的對象天生擁有一些神奇的方法,它們總被雙下劃線所包圍

    PHP利用二叉堆實現TopK-算法的方法

    相對 baidu 文本文件 過時 border 數據 http pan set 前言 在以往工作或者面試的時候常會碰到一個問題,如何實現海量TopN,就是在一個非常大的結果集裏面快速找到最大的前10或前100個數,同時要保證 內存和速度的效率,我們可能第一個想法就是利用排序

    Python 字符串的所有方法

    drive nes and tabs 英文 spa space cas ive 1 name = "my name is {name} and my age is {age}" 2 3 # 首字母大寫 4 name.capitalize() 5 # 統計某個字

    JavaScript | 創建對象的9種方法

    arr 常見 安全 圖解 margin cor *** 解析 刪除 ————————————————————————————————————————————————————————— 創建對象 標準對象模式 "use strict"; // *************

    cmake使用方法

    views iostream cross grep linu 文件內容 files 主目錄 動態 cmake 簡介 CMake是一個跨平臺的安裝(編譯)工具,可以用簡單的語句來描述所有平臺的安裝(編譯過程)。他能夠輸出各種各樣的makefile或者proj

    JS中的call、apply、bind方法

    面試 glob ble ole 內部 修改 sta illegal 解決 bind 是返回對應函數,便於稍後調用;apply 、call 則是立即調用 。 apply、call 在 javascript 中,call 和 apply 都是為了改變某個函數運行時的上下文(

    Java中的main()方法

    普通 什麽 javac 無限 reflect ase 理解 jvm cep 在Java中,main()方法是Java應用程序的入口方法,也就是說,程序在運行的時候,第一個執行的方法就是main()方法,這個方法和其他的方法有很大的不同,比如方法的名字必須是main,方法必須

    [js高手之路]原型對象(prototype)與原型鏈相關屬性與方法

    隱式 之前 username tar uname create pro getproto .get 一,instanceof: instanceof檢測左側的__proto__原型鏈上,是否存在右側的prototype原型. 我在之前的兩篇文章 [js高手之路]構造函數的基