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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

每天一道LeetCode-----将数字集转成字母集,计算有多少种转换方式

發(fā)布時(shí)間:2024/4/19 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 每天一道LeetCode-----将数字集转成字母集,计算有多少种转换方式 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Decode Ways

原題鏈接Decode Ways

每一個(gè)數(shù)字和一個(gè)字母對(duì)應(yīng),總共有26個(gè)字母,對(duì)于每一個(gè)或每?jī)蓚€(gè)數(shù)字,都有可能將其轉(zhuǎn)化成字母,計(jì)算有多少中轉(zhuǎn)換形式

以1221為例,所有的轉(zhuǎn)換形式為1->’A’,2->’B’,12->’L’,21->’U’,22->’V’,所有可能的轉(zhuǎn)換結(jié)果是

  • ABBA ((1)(2)(2)(1))
  • ABU ((1)(2)(21))
  • AVA ((1)(22)(1))
  • LBA ((12)(2)(1))
  • LU ((12)(21))

假設(shè)給出的數(shù)字序列是s[0, 1, …, n],令dp[i - 1]表示s[0, 1, …, i-1]這個(gè)數(shù)字序列能夠表示的所有轉(zhuǎn)化結(jié)果個(gè)數(shù),那么如何計(jì)算dp[i]呢

對(duì)于s[0, 1, …, i]這個(gè)數(shù)字序列的轉(zhuǎn)化結(jié)果,可以分成兩部分計(jì)算

  • 由s[0, 1, …, i-1] + s[i]組成,即所有轉(zhuǎn)化形式是s[0, 1, …, i-1]的轉(zhuǎn)換結(jié)果后加s[i]表示的字母。如1221可以表示成由122的轉(zhuǎn)換結(jié)果后加(1)表示的字母,即集合[ABB, AV, LB] + [A] = [ABBA, AVA, LBA],dp的表示形式為dp[i] += dp[i - 1]
  • 由s[0, 1, …, i-2] + s[i-1, i]組成,即所有轉(zhuǎn)化形式是s[0, 1, …, i-2]的轉(zhuǎn)化結(jié)果后加由s[i-1, i]表示的字母。如1221可以表示成由12的轉(zhuǎn)換結(jié)果后加(21)表示的字母,即集合[AB,L] + [U] = [ABU, LU],dp的表示形式為dp[i] += dp[i - 2]

所以直接動(dòng)態(tài)規(guī)劃計(jì)算即可,dp[i]與dp[i - 1]和dp[i - 2]有關(guān),不過(guò)有幾個(gè)邊界條件,尤其注意’0’無(wú)法轉(zhuǎn)換成對(duì)應(yīng)字母的情況

  • s[i] == ‘0’,s[i]不能表示字母,此時(shí)dp[i]與dp[i - 1]無(wú)關(guān)
  • s[i - 1] == ‘0’,s[i-1, i]不能表示字母,此時(shí)dp[i]與dp[i - 2]無(wú)關(guān)
  • i == 0 && s[0] != ‘0’,此時(shí)dp[0] = 1
  • i == 1 && s[0] != ‘0’ && toNumber(s[0, 1]) <= 26,此時(shí)dp[1] = 2

代碼如下

class Solution { public:int numDecodings(string s) {if(s.empty()) return 0;vector<int> dp(s.size(), 0);for(int i = 0; i < s.size(); ++i){/* 由s[0,1,...,i-1]+s[i]組成 */if(s[i] != '0')dp[i] += (i == 0) ? 1 : dp[i - 1];/* 由s[0,1,...,i-2]+s[i-1,i]組成 */if(i > 0 && s[i - 1] != '0' && ((s[i - 1] - '0') * 10 + (s[i] - '0') <= 26))dp[i] += (i == 1) ? 1 : dp[i - 2];}return dp[s.size() - 1];} };

代碼中處理了i == 0和i == 1的情況,因?yàn)閕 == 0時(shí)dp[i - 1]無(wú)意義,i == 1時(shí)dp[i - 2]無(wú)意義

為什么程序中是dp[i] += dp[i - 1]而不是dp[i] += 1 + dp[i - 1]

因?yàn)閐p[i - 1]表示由s[0, 1, …, i-1]表示的字母集,后面追加一個(gè)字母后個(gè)數(shù)沒(méi)有改變

以1221為例,假設(shè)i == 3,則s[0, 1, …, i - 1]表示的字母集是[ABB, AV, LB],個(gè)數(shù)dp[i - 1]是3

當(dāng)后面追加s[i]表示的字母A時(shí),字母集變?yōu)閇ABBA, AVA, LBA],個(gè)數(shù)沒(méi)變,所有dp[i] = dp[i - 1]

當(dāng)然,dp[i]在初始化時(shí)都至為0,所以只需要+=操作即可


Decode Ways II

原題鏈接Decode Ways II

要求和上面一樣,不同的只是數(shù)字集s中可能包含’*’,這個(gè)符號(hào)可以表示1到9任意一個(gè)數(shù)字

思想還是動(dòng)態(tài)規(guī)劃,但是要處理的情況變多了,比如

  • “*”可以可以表示”1”,”2”,…,”9”
  • “*2”可以表示”12”,”22”
  • “1*”可以表示”11”,”12”,…,”19”
  • “3*”不能表示任何一個(gè)二位數(shù)的數(shù)字,因?yàn)槌^(guò)了”26”

對(duì)于s[0, 1, …, i]由s[0, 1, …, i-1]+s[i]組成的情況,只是簡(jiǎn)單的多出s[i] == ‘*’的情況而已

而對(duì)于s[0, 1, …, j]由s[0, 1, …, i-2]+s[i-1, i]組成的情況,s[i-1, i]需要考慮多種情況,包括

  • s[i - 1] == ‘*’ && s[i] != ‘*’
  • s[i - 1] != ‘*’ && s[i] == ‘*’
  • s[i - 1] == ‘*’ && s[i] == ‘*’
  • s[i - 1] != ‘*’ && s[i] != ‘*’

當(dāng)然,無(wú)論多出多少種情況也都不能忽略i == 0和i == 1的情況

首先考慮s[0, 1, …, i]由s[0, 1, …, i-1]+s[i]組成的情況

  • 當(dāng)s[i] == ‘‘時(shí),s[i]可以表示9種數(shù)字,那么s[0, 1, …, i-1]后加s[i]時(shí)的組合個(gè)數(shù)就是dp[i - 1] 9。比如s[0, 1, …, i-1]表示的集合只有[A]一個(gè),而s[i]可以表示’A’,’B’,…’J’九種,所以s[0, 1, …, i]表示的集合就變?yōu)閇AA, AB, AC, AD, …, AJ]九種,自然是dp[i - 1] * 9
  • 當(dāng)s[i] != ‘*’時(shí),s[i]只可以表示1種數(shù)字,那么dp[i] += dp[i - 1]即可

再考慮s[0, 1, …, i]由s[0, 1, …, i-2]+s[i-1, i]組成的情況

  • 當(dāng)s[i - 1] == ‘*’ && s[i] != ‘*’時(shí)
    • 如果s[i] <= ‘6’,那么有兩種即”1n”和”2n”(n表示s[i])
    • 如果s[i] > ‘6’,那么只有一種”1n”(n表示s[i]),因?yàn)椤?n”會(huì)超過(guò)”26”
  • 當(dāng)s[i - 1] != ‘*’ && s[i] == ‘*’時(shí)
    • 如果s[i - 1] == ‘1’,那么有9種即”11”,”12”,…,”19”
    • 如果s[i - 1] == ‘2’,那么有6中即”21”,”22”,…,”26”
    • 如果s[i - 1] < ‘1’ || s[i - 1] > ‘2’,沒(méi)有字母可以表示
  • 當(dāng)s[i - 1] == ‘*’ && s[i] == ‘*’時(shí)
    • 有15種可能即”11”,”12”,….,”19”,”21”,”22”,…,”26”
  • 當(dāng)s[i - 1] != ‘*’ && s[i] != ‘*’時(shí)
    • 如果s[i-1, i]表示的數(shù)字小于等于26,有1中可能
    • 如果s[i-1, i]表示的數(shù)字大于26,沒(méi)有字母可以表示

代碼如下

class Solution { public:int numDecodings(string s) {if(s.empty()) return 0;long long int base = 1;for(int i = 0; i < 9; ++i)base *= 10;base += 7;vector<long long int> dp(s.size(), 0);for(int i = 0; i < s.size(); ++i){if(s[i] != '0'){dp[i] += (s[i] == '*') ? ((i == 0) ? 2 : dp[i - 1] * 2) : ((i == 0) ? 1 : dp[i - 1]);}if(i > 0 && s[i - 1] != '0' && (s[i - 1] == '*' || s[i] == '*' || ((s[i - 1] - '0') * 10 + (s[i] - '0') <= 26))){if(s[i - 1] == '*' && s[i] != '*')dp[i] += (s[i] <= '6') ? ((i == 1) ? 9 : dp[i - 2] * 9) : ((i == 1) ? 1 : dp[i - 2] * 1);else if(s[i - 1] != '*' && s[i] == '*' && s[i - 1] <= '2')dp[i] += (s[i - 1] == '1') ? ((i == 1) ? 9 : dp[i - 2] * 9) : ((i == 1) ? 6 : dp[i - 2] * 6);else if(s[i - 1] == '*' && s[i] == '*')dp[i] += (i == 1) ? 15 : dp[i - 2] * 15;else if(s[i - 1] != '*' && s[i] != '*')dp[i] += (i == 1) ? 1 : dp[i - 2] * 1;}dp[i] %= base;}return dp[s.size() - 1];} };

好多都是用了嵌套()?:表達(dá)式,如果不容易理解可以拆開(kāi)


感覺(jué)這兩道題不是在考動(dòng)態(tài)規(guī)劃而是在考腦筋急轉(zhuǎn)彎啊,各種情況想的腦袋疼

與50位技術(shù)專家面對(duì)面20年技術(shù)見(jiàn)證,附贈(zèng)技術(shù)全景圖

總結(jié)

以上是生活随笔為你收集整理的每天一道LeetCode-----将数字集转成字母集,计算有多少种转换方式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。