tft每日頭條

 > 生活

 > 求單調區間與最值

求單調區間與最值

生活 更新时间:2024-09-30 11:02:55

今天通過一道有趣的題目來展示做題時思考的過程是怎樣一步步演變的,隻講思路不談編程和代碼,您也可以理解成它就是一個解題過程的筆記,其核心思想也是适用于大多事情的并不專指編程。

為什麼用這題?難度适中但想做好需要一定的動腦思考的能力和邏輯推理。


開始正文

看題:

給你兩個正整數A和B(1<=A<=B<=100000)求A~B(包含A和B)的所有回文數個數。

什麼是回文數?請看:

将最高位與最低位、次高位與次低位……進行比較,若彼此相等則為回文數。例如:121,222,456654,45654,這個應該都能懂吧。

一句話:‘‘回文數’’就是不管從左向右還是從右向左讀這個數的大小始終保持不變。

答題要求:

A和B之間(包含A和B)的所有回文數個數,沒有輸出0。

示例:

1.給于兩個數A、B分别是2、8 得出的結果是:7

2.給于兩個數A、B分别是12、21 得出的結果是:0

解讀示例1:

結果為什麼是7?首先起始數是“2”,不管從左到右還是從右到左讀他還是表示其本身2不變,所以滿足“回文數”的定義,同理8也一樣所以這兩個數本身就是回文數那自然的從2到8的所有數也都是“個位數‘’自然也滿足回文數的定義。

求單調區間與最值(有趣的求區間回文數)1

計算公式為:8-2 1=7

可以得到簡單的計算公式:8-2 1=7

解讀示例2:

首先起始數12本身很明顯不滿足回文數的定義所以不是回文數,下一位13以及直到21也沒有一個滿足的所以它們之間有0個回文數。

求單調區間與最值(有趣的求區間回文數)2

沒有回文數

通過這兩個示例大家對回文數有了進一步的了解也知道了題目要的計算結果是怎麼來的了。

新發現:

個位數全是回文數,并且如果兩個回文數都是個位數可以直接相減後 1得到其全部區間的個數。之所以可以是因為正好和自然數是一樣從小到大依次排列的所以也可以像自然數一樣運算。

計算過程為:C=B-A 1,示例1已驗證。

到這自然還會想到是不是其它回文數也能這樣用上述的公式進行計算呢?簡單的驗證下就可以很明顯地知道并不是所有情況都可以這樣簡單地得到結果。

如:8-15之間共有8、9、10、11、12、13、14、15其中是回文數的隻有8、9、11這3個那我們明顯不能用15-8 1或11-8 1來計算出正确結果。

初入江湖

不能用的話怎麼辦?有沒有其他公式?我們可以先想想看。

大部分沒有類似經曆的人短暫的思考後可能沒有想出來這也很正常,沒有經過大量的練習很難能直接想到一個比較理想的方式優雅地計算出來。

既然不能一次想出一個好的辦法那我們能不能來點簡單粗暴的?

簡單粗暴的是什麼樣?

回想一下剛才舉例求8-15之間的回文數個數的時候的情景,雖然不能通過前面的公式得到答案,但你知道不知道答案是3?

怎麼知道的?

這應該是人類長期的學習和生活經驗的結果,也是以前人工智能進步比較慢的原因,我們可以根據一些信息進行高效的自我學習,然後基于經驗快速的推理出結果。

這是很自然地下意識的一個過程快速有效,像呼吸般順暢自然。

分析一波潛知識下的思考過程。

當我們看到起始數8的時候自然會去看他是不是一個回文數?

如果是我們會在心裡默默地給我們設想的一個虛拟計數器 1

然後查看下一個數字9(這9是怎麼來的?我們知道自然數8後面的數是9,兩個相鄰的自然數之間差1)到9的時候我們又會重複上述過程先看是不是回文數?是就給虛拟計數器再 1不是就不加。

此過程往複一直到最後一個15為止,最後大腦中的虛拟計數器已經變成了3

核心邏輯:判斷一個數是不是回文數?是就給虛拟計數器 1不是就不

邏輯過程:(非标準流程圖隻為示意)

求單調區間與最值(有趣的求區間回文數)3

上面的邏輯肯定是可以求出A、B之間包含多少回文數的,有了思路編寫代碼隻是技巧和時間問題了略過。

那上面的邏輯過程實際上就是最簡單粗暴的一種方式來得到結果。

優點:思路簡單很容易想到也符合正常思維方式“簡單而有效”。

缺點:實際上需要不停判斷A和B之間的N個數是不是回文數,當區間較小的時候還好,如果區間特别大的時候問題就更明顯,整個過程需要計算太多次了,不信可以自己計算下1-100000間有多少個回文數

相信沒有人真的會去計算吧[笑哭]

我們在使用沒那麼優雅的方式解決了問題後還要再思考下難道沒有更好的辦法了嗎?

如果實際中就不允許計算這麼多次怎麼辦?


拿下首殺

思考下造成我們計算這麼多次的原因是什麼?

因為我們不知道A和B之間具體有那些回文數,所以隻能把從A到B所有的數都試一次。

這其實就是暴力碰撞。

就像你要在一個城市統計有多少和你重名的人但你又不知道他們都住在哪裡,為了能找到全部的人,你選擇了一個最容易想到的方法,就是從這個城市的第一戶人家開始問起,一家又一家不停的問下去直到問完全部的為止,雖然有效但不夠高效,那怎樣才能高效起來?當然是減少去尋找無效的目标啦,也就是我們這裡的無效數字判斷過程啦。

具體怎麼做?

之所以要一個個的判斷是因為我們不知道區間有那些數是回文數所以隻能假設全部都可能是潛在的目标。

那我們能不能換個思路?

嘗試計算出任意回文數的下一個回文數是多少呢?

有人可能會問為什麼這樣做?

假設從回文數11開始:

如果按之前的辦法找到下一個回文數22我們要經過11,12,13,14.....19,20,21,22這麼多數的檢查判斷而有效的其實隻有11和22兩個。

如果我們直接可以根據11算出下一個回文數是22那是不是就簡單了?

稍花點時間仔細觀察和思考後發現顯然是可以的。

求單調區間與最值(有趣的求區間回文數)4

可以類似這樣在紙上畫畫方便觀察

最終是可以找到方法計算出下一位回文數的,為了節省篇幅且這部分也不作為重點所以直接略過就不展示推理過程,此處省略三千字[笑哭]

假設現在已掌握了根據一個回文數計算出下一位回文數的方法了,是不是可以這樣去思考?

假設己知從A開始的第一位回文數是什麼(實際上我們還需要根據A計算出最接近的一個有效回文數,同樣不是重點先選擇勿略了強行開啟外挂獲得此技能[666])那麼根據當前回文數又能算出下一位的回文數,這樣我們是不是就可以無限算下去直到最後的B為止并且在大小超過B之前每算一位就讓計數 1之樣最後是不是就得到了總個數?

求單調區間與最值(有趣的求區間回文數)5

最後一次推算出的88大于85屬于無效

通過上面的示例可以很明顯的看到我們從A到B的過程變短了,每次計算的都是一位有效的回文數自然也省去了判斷是否是回文的步驟,直接跳過了所有無效目标從而減少了整個過程,當區間越大的時候效果越明顯怎麼樣是不是比之前的方法稍優雅了那麼一點了?

核心邏輯:根據一個回文數算出下一個回文數,不大于B時計數器 1,大于停止。

邏輯過程如下:

求單調區間與最值(有趣的求區間回文數)6

可以和上次的對比一下邏輯變得更加的簡單明了,全部的核心算法都在如何算出下一個回文數這部分,并且還過濾掉了大量的無效計算和判斷,同理有了邏輯後寫出代碼自然也不是太難。

恭喜到這我們已經實現了第一次的邏輯優化過程,我們可以有那麼點點成就感了,是不是隻要稍加觀察和思考也是可以想到更好的方案的,其實思考就是反複觀察一些現像,大膽假設推理發現其中可以利用的規律,是不是沒有那麼難?

大家現在可以稍加休息一會,放松一下大腦,休息時可以在潛意識中問問自己是不是還有更好的辦法?


推上高地

是否有了新的想法呢?

帶着您的想法和疑問我們一起接着思考下去看看是否有共同的發現和奇思妙想。

當沒有直接靈光昨現獲得新的靈感的話,那這時候我們不妨去思考一下剛才的改進版有哪些優缺點?

優點:确實節省了不少的計算次數,因為過濾了大量無效數,讓我們每次到下一位就直接是最理想的那個回文數,自然也不用再去判斷是不是回文數了。

缺點:要不停地去計算出每一位有效的回文數,其實這本身也是個不小的計算量,并且我們尋找生成下位回文數的辦法這個過程也有點點麻煩,需要我們發現變化規律最終找到一個通用的解,這過程以至于可能又要多掉兩根頭發[衰]

綜合優缺點我們好像看到了一點前進的方向,我們現在需要的是最好又能知道區間有那些回文數又不想去通過太多的計算來實時算出來并且最好還能讓邏輯再簡單點(要啥自行車)[吐血]

元芳你怎麼看?

回大人,應該如此之般......之般一如此。

好了先說下我的思路,大家看看是否和你想法有些相似?

先說個基本都聽過或者用過的東西,‘‘字典”不管你是新華字典還是成語字典等等其作用和原理都差不多,就是通過一個關鍵信息來查詢到所對應的另一個相關信息,道理我們都懂,但是和這題有啥關系呢?

是否可以大膽地設想下假如我們撿到了這樣的一本字典。

字典的每一頁都有一個回文數,并且每頁都是按照回文數從小到大的順序排下去的就像這樣‍[機智]

求單調區間與最值(有趣的求區間回文數)7

求單調區間與最值(有趣的求區間回文數)8

圖中每個方框表示為字典中的一頁且是從小到大連續排列的,圓中的數字表示是當前頁的一個回文數右下角的數表示這個回文數所在的頁,也就是該回文數對應的頁碼。

當有了這樣的一本字典那事情就要容易很多了,你問怎麼個容易法?

那驗證下如果現在有兩個數A、B。

A=8,B=44,為了方便先假定A和B就都是回文數。

我們可以去拿着A去翻下字典看下它的頁碼是多少,對照字典可以知道回文數8對應的頁碼正好也是8,回文數44對應的頁碼是13。

有了上述信息我們就可以去運用個位數回文數的計算公式了。

什麼?你問我為什麼之前不能現在卻可以了?我們現在計算的并不是回文數本身而是它對應的頁碼哦[機智]

之前的公式是這樣的:C=B-A 1

代入數字驗證:44-8 1=37 肉眼可見的結果明顯不對

變化一下後是這樣的:C=B頁碼-A頁碼 1

驗證:13-8 1=6 結果對不對?數下呗8、9、11、22、33、44正好六個

好像可行啊去偷樂一下吧[舔屏]

可能還有人不放心,很好,那可嘗試向我這樣自己去畫畫多驗證一下。

怎樣?驗證完了是不是發現邏輯确實沒毛病?

這裡的核心原理就是人為的去給本來無法直接建立關系的二者試着去建立他們的關聯性從而創造出我們需要的某種規律來适應我們的邏輯。

暫時别高興太早先冷靜下來[奸笑]

剛才所有的前提都是在假設已經有了這樣一本字典,并确實可以根據一個回文數查出它對應的頁碼,但我們真的有嗎?好像并沒有吧?最少目前編程環境中肯定沒有的那問題來了是不是要白高興了?

既然沒有現成的那能不能自己造一個?剛才不就自己動手畫了一些嗎?

那準備自己打造字典了就要考慮到這個字典我們應該怎麼去描述它?它應該有什麼樣的功能(類似于數據結構的概念先不過多展開)更多精力放在邏輯上。

歸納下創建字典需要解決的問題:

①如何描述這個字典?

先簡單認為它是具有一個鍵值對關系的結構、這個鍵永遠指向他的值,鍵用來保存回文數,值用來保存這個回文數對應的頁碼,就像下圖這樣。

求單調區間與最值(有趣的求區間回文數)9

鍵(key):可以理解為一個關鍵字。

值(value):可以理解為通過這個關鍵字所能精準找到的内容。

②它的功能是什麼?

根據一個鍵(回文數)精準快速地查出這個鍵所對應的值(回文數的頁碼)

有了來描述和保存内容的結構後我們還需要考慮一個關鍵問題,這些回文數還好說之前我們已經可以根據一個回文數生成下一個回文數了,但每個回文數的頁碼好像并不知道啊?

再想想之前觀察到的一些關鍵信息(個位數的回文數正好與其自然數排列位置對應的)

我們可以利用這點來做為基準點然後往後連續生成回文數與頁碼,當回文數如果是連續排序的那他的頁碼也應該是連續的,隻要保證生成的回文數是正确且連續的就行,頁碼不同于回文數的地方在于隻需做簡單的自然增長就可以。(每次 1)

準備好這些後實際在理論上已經可以生成一個任意長度的回文字典了[泣不成聲]

有了字典就可以按之前的邏輯算出A到B有多少個回文數啦!

不過我們在查A、B對應的頁碼前還需要再算出A與B各自最接近的有效回文數,因為實際情況中A與B并不一定就正好是回文數所示要确保最終是用回文數去查字典的,此過程中也有點小細節需要注意比如A=12,那他的有效回文數應該是22而不是11,A=21則回文數應是22而不是33或11等一些小的細節要注意。

核心邏輯:生成一個字典,根據一個回文數通過字典查出它對應的頁碼。

整體邏輯流程:

求單調區間與最值(有趣的求區間回文數)10

怎麼樣邏輯上是不是更簡單啦?而且計算量也少了很多,主要部分的計算量也隻是在生成字典這一部分,是不是感覺哇原來可以這麼簡單呀?

到這我們好像終于可以松口氣啦!此時低頭看了眼地面上的頭發雖有些淡淡的憂傷,不過也總算是得到不錯的結果,是不是有點小安慰小激動?

此時的你是不是已經在等我的最後總結了?

好吧我們一起來回顧下經過的幾次邏輯演變過程。

①先是經過短暫的觀察和思考後我們比較容易地想到了一種簡單粗暴的方式,不停的一個個去判斷計算直到檢查完所有可能的目标。

②經過對上述方法的進一步分析其優缺點後我們得到了一個初始的改進方案,盡量減少了不必要的計算過程從而讓邏輯和效率都更′‘合理些’’。

③分析前兩種本質上還都是從一個目标不停移動到另一個目标的原理隻是移動的過程稍高效了一些,那有沒有不需要這種方式而能像個位數回文數一樣簡單的直接得到結果呢?因為很多情況下無法直接做到,我們又轉換了思路使用了常見的字典的工作原理來幫助我們實現了這樣的目的。

怎麼樣一路走來是不是感覺沒有那麼輕松,但也能在經過努力後跟上了節奏?

很多時候隻要願意去觀察分析事物的本質與運行規律,都是可以用來大膽假設和推理出一些信息的,這些信息并不一定每條都有用,可能有的成功有的失敗了,但在這個過程中也許某些信息産生出新的靈感,這樣不斷的嘗試後肯定是可以找到一條正确的道路的,練習的趆多思考的趆多那麼你的思考速度和感覺就會慢慢變得更加高效敏銳!

來到之恭喜聰明的你猜對了事情還沒結束,怎麼可能就這樣收場呢

不過是真的最後憶次了

點掉水晶

我們把思緒回到最後的“查字典”方案中去,再看憶眼它真的是很完美了嗎?

優點:現在可以直接根據字典查出回文數對應的頁碼了也沒有煩雜的移動計數的過程了。

缺點:所有的前提都是要提前準備好一個最少包含了A、B兩個回文數區間所有回文數的字典這本身也比較麻煩,且也會出現如果區間很大的話要生成一個比較大的字典,從效率的角度來說明顯不太友好不高效。

根據優缺點思考一下接下來該怎麼辦?

現在是不是很自然向能否不用生成字典而直接知道每個回文數的“頁碼”這個方向思考了?

看你現在不是也慢慢學會了如何尋找問題的關鍵來針對性思考了?

那再來最後一次,這次會稍多點細節看是如何最終優化的。

如何才能實現不要字典也能知道每個回文數的頁碼呢?關鍵還在字典上。

我們把之前的字典進行平鋪式展開後再觀察它是否有某種規律

求單調區間與最值(有趣的求區間回文數)11

為了方便觀察直接跳過了大部分個位數隻保留9

為了方便觀察直接跳過了大部分個位數隻保留一個9做為起始參考,因個位數的特殊性先可以直接先忽略掉方便觀察。

請認真觀察下字典中的鍵(K)和值(ⅴ)是否有着某種規律,相信大家隐約感覺到了一些。

如果還沒有頭緒的話可以進一步縮小觀察範圍,可以自己在紙上畫下。

如果還不能找到一個比較通用的方式的話那可以換個角度看問題,是不是可以先觀察更明顯的雙位數的規律,然後再往後依次解決後面的,如下圖。

求單調區間與最值(有趣的求區間回文數)12

雙位數回文數

相信到這大家或多或少是可以發現他們變化的規律的而且不隻是一種。

廢話已然太多了[奸笑]所以我就不帶大家一步步推算了。

我說其中一個相對簡單的方法但不一定是最優的,主要是給大家提供一個思路。

經過觀察後我發現雙位數的頁碼就是本身中的一位再加9

如:11就是取任意一位得到1然後1 9=10,66一〉6 9=15,99一〉9 9=18

是不是沒毛病?至于為什麼 9道理不難理解,不明白的可以把這先想通了會更有幫助。

雙位計算過程:任意一位 9=頁碼

那三位的回文數是否通用呢?我們可以去驗證下

如:101一〉1 9=10 明顯出現了問題好像不能直接通用那就再接着分析下三位數呗

求單調區間與最值(有趣的求區間回文數)13

三位回文數

同樣可以觀察到不止一種方法,那我還是保持之前的整個邏輯去思考既然你回文數增加了一位那我在取的時候能不能也多取一位?試呗!

如:101一〉前兩位(倒着也一樣)一〉10 9=19 好像可以?不放心就再來次。

如:989一〉98 9=107确實沒問題

那就趕緊再試下4位的回文數是不是可以用?

如:1001一〉10 9不對啊,難道取三位一〉100 9=109?沒毛病,再試1111一〉111 9=120 ????

*******什麼情況?不管用了啊?

這時候又需要再次思考下了其實和之前的道理差不多,不廢話。

依然取前兩位 9不過還要再多加個90

如:1001一〉10 9 90=109,1111一〉11 9 90=110,1551一〉15 9 90=114沒問題了。

那5位呢?接着試

如:10001一〉有了之前的經驗直接取三位一〉110 9 90=199沒錯,10101一〉101 9 90=200沒毛病。(可以自己驗證)

由于我們題目中最大數是100000六位數且不是回文數可以直接到此為止了,下面也是類似的情況。

整理下目前觀察到的所有規律:

①個位數本身就是頁碼

②兩位數,三位數分别取首位和前兩位 9得到頁碼

③四、五位數分别取其前2、3位 9 90

好了所有的公式都出來了,肯定可以根據一個回文數算出其對應的頁碼了。

現在主要解題邏輯變成下面這樣:

①首先求到A與B最近的有效回文數(注意其特殊情況)

②通過判斷回文數是幾位數去使用公式算出對應的頁碼

③C=B-A 1

核心邏輯:根據一個回文數通過字典查出它對應的頁碼。

整體邏輯流程:

求單調區間與最值(有趣的求區間回文數)14

最終邏輯過程

到之從邏輯方面來說已經差不多走到了當前題解的極緻,直擊問題根本沒有什麼多餘的東西,下面就是根據思路寫出代碼的問題了。

最後憶點點

一路堅持下來的勇士們是不是有些感觸呢?整個過程中并沒有使用過多的專業或高深的知識吧,都是一些基本的東西,卻能讓我們調動更多的精力去以一個相對原始的方式去思考激發更多的潛能。

建議特别是初學着遇到類似這種有點意思的題目時不要急着去想套公式而應該先自己嘗試用自己的思路去解決看看,不停的去挑戰自己的極限相信經常這樣的練習肯定會有不一樣的收獲。

篇幅問題一些細節沒有去講太多或有遺漏的地方在這表示抱歉,有疑問的也可以根據結論去反推我為什麼要這樣做?想講得太多有時會顧此失彼有機會再聊吧。

,

更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!

查看全部

相关生活资讯推荐

热门生活资讯推荐

网友关注

Copyright 2023-2024 - www.tftnews.com All Rights Reserved