日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

72.编辑距离105.前序中序遍历序列构造二叉树151.翻转字符串里的单词104.二叉树的最大深度76.最小覆盖子串110.平衡二叉树31.下一个排列

發布時間:2023/12/20 编程问答 37 豆豆

72.編輯距離

給你兩個單詞 word1 和 word2, 請返回將 word1 轉換成 word2 所使用的最少操作數 。你可以對一個單詞進行如下三種操作:插入一個字符,刪除一個字符,替換一個字符。

輸入:word1 = “horse”, word2 = “ros”
輸出:3
解釋:horse -> rorse (將 ‘h’ 替換為 ‘r’)
rorse -> rose (刪除 ‘r’)
rose -> ros (刪除 ‘e’)

  • 動規。首先題目說了可以對word1或者word2操作,只要變成相同的就可以,沒有要求變成兩個字符串的公共子串,那么刪除操作和填入操作是等價的,對word1刪除等價于對word2添加
    • 不考慮刪除實際上只有三種操作:①在word1添加②在word2添加③替換word1或者word2字符。這里說明一下,③中把1中的字符替換成2的字符和把2的字符替換成1的字符是等價的;而①和②是不等價的,比如"ab"和"a"你只能在word2添加字符b而不能在word1添加。
    • dp[i][j]表示前word1前i個字符和word2前j個字符的編程距離,如果word1[i]不等于word2[j],那么就可以通過word1或者word2尾元素進行上述三種操作變成相同的,因此狀態轉移方程如下:dp[i][j]=min(dp[i-1][j]+1,dp[i][j-1]+1,dp[i-1][j-1]+1)。
      需要注意的是,如果word1[i]等于word2[j],那么相同元素就不需要動了,狀態轉移到字符串前移一個元素dp[i][j]=dp[i-1][j-1]。這種方法對于需要在頭元素進行操作的情況也是適用的,舉個例子"aaabcdefggg"和"bcdef",計算時dp[i-1][j]會前溯到dp[i-3][j]把不等的去掉,實際上dp[i-1][j]的結果就是已經考慮了把word1尾指針前移的最優解。這種dp寫法是基于對尾元素進行操作的,也可以寫成對首元素操作,那樣的話遍歷方向要從字符串后往前。

    105.從前序與中序遍歷序列構造二叉樹

    給定兩個整數數組 preorder 和 inorder ,其中 preorder 是二叉樹的先序遍歷, inorder 是同一棵樹的中序遍歷,請構造二叉樹并返回其根節點。

    輸入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
    輸出: [3,9,20,null,null,15,7]

  • 一開始的想法是通過判斷先序遍歷節點的后驅在中序遍歷中的索引下標是不是在該節點之前,以此來確定一個節點的左孩子,但是要想直接找到右孩子情況非常復雜。(還要區分當前節點是左孩子還是右孩子,其左孩子的右孩子是不是為空…)。
  • 關于樹的算法從原子操作的角度思考非常重要,樹的定義本來就是一種遞歸,子樹也是一個樹,左子樹和右子樹拼接起來就是一顆新樹。中序序列中一個節點的左邊全是左子樹,右邊全是右子樹,通過左子樹的區間長度就可以找到前序序列中的左子樹區間。基于這種思想可以用迭代方法解決這個問題:
  • public TreeNode buildTree(int[] preorder, int[] inorder) { for(int i=0;i<preorder.length;i++)hashmap.put(inorder[i],i);return build(preorder,inorder,0,inorder.length-1,0,inorder.length-1);}public TreeNode build(int[] preorder, int[] inorder,int pl,int pr,int il,int ir){if(il>=inorder.length||pl>pr||il>ir)return null;int index=hashmap.get(preorder[pl]);int len=index-il,len2=ir-index;TreeNode root=new TreeNode(preorder[pl]);if(pl==pr)return root;root.left=build(preorder,inorder,pl+1,pl+len,il,index-1);root.right=build(preorder,inorder,pl+len+1,pl+len+len2,index+1,ir);return root;}

    151.翻轉字符串里的單詞

    給你一個字符串 s ,逐個翻轉字符串中的所有 單詞 。單詞 是由非空格字符組成的字符串。s 中使用至少一個空格將字符串中的 單詞 分隔開。請你返回一個翻轉 s 中單詞順序并用單個空格相連的字符串。

    輸入:s = “a good example”
    輸出:“example good a”

  • 用首尾雙指針,先把首尾多余的空格去掉,然后從后往前遍歷把一個個單詞添加進結果里,每次注意保存單詞最后一個字母。
  • 104.二叉樹的最大深度

    給定一個二叉樹,找出其最大深度。二叉樹的深度為根節點到最遠葉子節點的最長路徑上的節點數。

    1.略

    76.最小覆蓋子串

    給你一個字符串 s 、一個字符串 t 。返回 s 中涵蓋 t 所有字符的最小子串。如果 s 中不存在涵蓋 t 所有字符的子串,則返回空字符串 "" 。

    輸入:s = “ADOBECODEBANC”, t = “ABC”
    輸出:“BANC”

  • 雙指針法,每一輪循環先讓right指針先向右移動,直至指針區間包含模式串,再讓left開始向右移動直至left+1到right區間(首次)不包含模式串,此時雙指針之間即為一個覆蓋子串。但是這道題有一個比較麻煩的地方,模式串中的字符可以重復,因此難點在于兩個地方,如何判斷在right指針移動中首次包含字串left移動中首次不包含子串。我的做法如下:
    • 創建一個HashMap tmodel構建在模式串中每個字符和出現次數的映射,另一個HashMap del來存放兩個指針區間的模式串字符和對應在指針區間出現次數的映射關系。再設置一個ArrayList full容器,存放當前還需要匹配找到的字符串,初始list容器把模式串的字符全部填入(可以重復)。主串每找到一個模式串含有字符就在del中記錄出現次數加一,并從list中移除該元素(如果有),當full容器全部排空則說明首次匹配。
    • 左指針移動時,每找到一個模式串含有的元素就在del中對應字符次數減一,當該字符在del中出現次數等于tmodel中的次數時,則表明若刪去該字符,指針區間不包含子串。此時要記得在full中添加該字符(下次right右移找到該字符,即找到新的覆蓋子串)

    見鬼的是,只有一個主串長度比較離譜的用例沒通過,推測是容器擴容失敗溢出了。

    public String minWindow(String s, String t) {Map<Character,Integer> tmodel=new HashMap<>(),del=new HashMap<>();List<Character> full=new ArrayList<>();int i=0,resl=0,resr=s.length();while(i<t.length()){if(!tmodel.containsKey(t.charAt(i)))tmodel.put(t.charAt(i),1);elsetmodel.put(t.charAt(i),tmodel.get(t.charAt(i))+1);full.add(t.charAt(i));i++;}int left=0,right=0;while(left<s.length()&&right<s.length()){while(right<s.length()){char c=s.charAt(right);if(tmodel.containsKey(c)){if(full.contains(c))full.remove(Character.valueOf(c));if(!del.containsKey(c))del.put(c,1);elsedel.put(c,del.get(c)+1);}if(full.size()==0)break;right++;}if(right==s.length())break;while(left<s.length()){char c=s.charAt(left);if(tmodel.containsKey(c)){if(del.get(c)==tmodel.get(c)){if(right-left<resr-resl){resl=left;resr=right;}del.put(c,del.get(c)-1);full.add(c);left++;right++;break;}del.put(c,del.get(c)-1);}left++;}}if(resr<s.length())return s.substring(resl,resr+1);return s.substring(0,0);}

    110.平衡二叉樹

    給定一個二叉樹,判斷它是否是高度平衡的二叉樹。

    輸入:root = [3,9,20,null,null,15,7]
    輸出:true

  • 本質上求二叉樹的深度,判斷左子樹深度和右子樹深度之差是否大于1。
  • 31.下一個排列

    給你一個整數數組 nums ,找出 nums 的下一個排列。必須原地修改,只允許使用額外常數空間。整數數組的下一個排列是指其整數的下一個字典序更大的排列。

    輸入:nums = [1,2,3]
    輸出:[1,3,2]

    輸入:nums = [3,2,1]
    輸出:[1,2,3]

  • 掃描兩邊整個數組,第一遍從后往前找,找到第一個非降序的位置,第二遍掃描該非降序數組,找到比首元素大的數中最小的元素,使其與首元素交換,并使首元素后的數組首尾兩兩交換


  • 今日總結

    刷題

    總結

    以上是生活随笔為你收集整理的72.编辑距离105.前序中序遍历序列构造二叉树151.翻转字符串里的单词104.二叉树的最大深度76.最小覆盖子串110.平衡二叉树31.下一个排列的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。