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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

每列大于0的个数_题目1342——把一个数字减少到0的步骤数

發(fā)布時(shí)間:2024/8/1 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 每列大于0的个数_题目1342——把一个数字减少到0的步骤数 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

封面來自leetcode.com

題目描述

給定一個(gè)非負(fù)整數(shù),返回把這個(gè)數(shù)減少到0的操作步驟數(shù)。當(dāng)給定的數(shù)是偶數(shù)時(shí),把它除以2;當(dāng)給定的數(shù)是奇數(shù)時(shí),把它減去1。

示例

例1

輸入:num = 14

輸出:6

解釋:

  • 14是偶數(shù),除以2,得7,步數(shù)+1
  • 7是奇數(shù),減去1,得6,步數(shù)+1
  • 6是偶數(shù),除以2,得3,步數(shù)+1
  • 3是奇數(shù),減去1,得2,步數(shù)+1
  • 2是偶數(shù),除以2,得1,步數(shù)+1
  • 1是奇數(shù),減去1,得0,步數(shù)+1
  • 結(jié)束

    約束條件

    num大于等于0,并且小于等于10的6次方

    題解

    初看這道題,示例給出的邏輯就已經(jīng)形成代碼邏輯,所以只需要用代碼把文字描述實(shí)現(xiàn)出來,便得出解法

    /*** @param {number} num* @return {number}*/ var numberOfSteps = function(num) {var ans = 0while (num != 0) {if (num % 2 === 1) { num--} else {num = num / 2}ans++}return ans };

    怎樣解不管時(shí)間復(fù)雜度和空間度其實(shí)都不大,因?yàn)轭}目本身有點(diǎn)像在做二分法,時(shí)間復(fù)雜度是O(log n),空間復(fù)雜度只用到了一個(gè)計(jì)數(shù)變量,所以是O(1)。

    所以題目解法本身看上去的確已經(jīng)沒有什么優(yōu)化的空間了。

    但是看了官方解法(我是會(huì)員所以能看到)中提到一句很好的話,在這里分享給大家“解法2和解法3并不會(huì)改變時(shí)間復(fù)雜度,但它們對(duì)于問題提供了一種不同的思考方式,希望大家能夠擴(kuò)展自己解決問題的思路”。原話如下:

    Approach 2 and 3 don't change the time complexity, but they offer a different way of thinking about the problem that studying will hopefully help you expand your problem solving skills!

    話已至此,那我們不妨看看另外兩種“不會(huì)降低時(shí)間復(fù)雜度”的解法。看完發(fā)現(xiàn),果然。其實(shí)leetcode題做個(gè)幾道,如果有悟性的同學(xué),都會(huì)發(fā)現(xiàn)萬事萬物都有一定的套路(即規(guī)律)。這里指的就是“位運(yùn)算”。

    位運(yùn)算這東西對(duì)于不愿意關(guān)注的人來說,可能一直是一個(gè)很抵觸、很陌生的東西,感覺很難,而且業(yè)務(wù)中也不會(huì)用到。但對(duì)于研究過的同學(xué)都知道,位運(yùn)算是最接近計(jì)算機(jī)運(yùn)作原理的計(jì)算方式,自然效率也因?yàn)楦咏暗讓印倍兏咭恍?/p>

    這就像是你本來可以用軟件封裝給你的一些工具方法實(shí)現(xiàn)你想做的事,但軟件本身給你預(yù)留了一個(gè)直接訪問底層的API,你可以自己去實(shí)現(xiàn)軟件提供給你的這些方法,并且能玩出更多的花樣,順帶收益更高的運(yùn)算效率。

    位運(yùn)算就像這樣的一個(gè)東西。

    解法二

    仔細(xì)觀察發(fā)現(xiàn)我們的每次操作不是“除以2”就是“減去1”。

    在二進(jìn)制中,當(dāng)一個(gè)數(shù)是奇數(shù)時(shí),其末尾一定是1,而偶數(shù)時(shí),其末尾一定是0。所以按照題目要求:

    當(dāng)末尾是1,即奇數(shù)時(shí),我們對(duì)這個(gè)二進(jìn)制進(jìn)行減1,隨之其末尾變成0,即偶數(shù),需要除以2,在二進(jìn)制運(yùn)算中除以2就是向右移動(dòng)1位,這樣這個(gè)二進(jìn)制數(shù)則會(huì)少一位,當(dāng)重復(fù)如此操作直至所有位都移完,這個(gè)數(shù)就變成0了。

    那么對(duì)于本題結(jié)果的計(jì)算便轉(zhuǎn)換成了二進(jìn)制操作移位的步數(shù),即遇到1,需要操作2步,即減1+右移;遇到0,只需操作1步,即右移。

    所以題目的解法變成目標(biāo)數(shù)轉(zhuǎn)換成二進(jìn)制格式后中“1的個(gè)數(shù)*2+0的個(gè)數(shù)*1”,即本文的封面圖。

    但這里有個(gè)需要注意的邊界問題,即當(dāng)二進(jìn)制數(shù)移動(dòng)到只?!?”時(shí),只需要減1,即得到結(jié)果,需要停止計(jì)算。也就是對(duì)于最后一個(gè)1的操作數(shù)不需要乘2,所以要在總的結(jié)果數(shù)中減1即可。

    在這一點(diǎn)上,官方題解中也有一句很好的告誡“我們都知道,因?yàn)橐粋€(gè)錯(cuò)誤導(dǎo)致滿盤皆屬的情況經(jīng)常發(fā)生,我們應(yīng)該對(duì)情況的邊界小心留意“。原話如下:

    as we know this "off-by-one-error" will always happen (except when the initialnumis0, we need to be careful of that edge case too!).

    代碼如下:

    /*** @param {number} num* @return {number}*/ var numberOfSteps = function(num) {if (num === 0) return numvar ans = 0num = num.toString(2)for (const item of num) {if (+item === 1) {ans+=2} else {ans+=1}}return ans-1 };

    解法三

    解法二的弊端在于,它相比解法一反而增加了空間復(fù)雜度,因?yàn)槲覀儼言镜恼麛?shù)存儲(chǔ)為了字符串,字符串占用的空間會(huì)比整數(shù)多。

    于是解法三中的優(yōu)化是用“逐位比較”取代“將整數(shù)轉(zhuǎn)換為二進(jìn)制字符串”。

    我們知道“按位與”操作(&)是可以比較出某一位是否是1的,因?yàn)楫?dāng)某位是1時(shí),與1操作會(huì)得到1,而當(dāng)某位是0時(shí),與1操作會(huì)得到0。

    所以我們完全無需像解法中把數(shù)字轉(zhuǎn)換為二進(jìn)制字符串,直接將原整數(shù)依次和一個(gè)只有固定位上是1的數(shù)進(jìn)行與操作,這個(gè)固定位我們可以控制為從末尾到首位,而這個(gè)操作則只需將1依次進(jìn)行乘2操作(或左移)即可。

    至于統(tǒng)計(jì)操作步驟的規(guī)則依然如解法二,即遇到位值為1時(shí),計(jì)2步,遇到位值為0時(shí),計(jì)1步,最終結(jié)果減1。

    因?yàn)榕c操作的特點(diǎn)是,兩個(gè)操作數(shù)都為1,結(jié)果才為1,只要有一個(gè)操作步為1,結(jié)果都會(huì)0。

    而我們提供的那個(gè)動(dòng)態(tài)的數(shù)是確定的依次逐位為1,所以如果某一次計(jì)算的結(jié)果是0,則證明所有位都不相同,即與我們的動(dòng)態(tài)數(shù)當(dāng)前為1對(duì)應(yīng)位置上的數(shù)為0,則步數(shù)計(jì)算應(yīng)該+1,否則+2。

    代碼如下

    /*** @param {number} num* @return {number}*/ var numberOfSteps = function(num) {if (num === 0) return numvar ans = 0;var flag = 1;while (flag <= num) {const temp = flag & numif (temp !== 0) {ans = ans + 2;} else {ans = ans + 1;}flag = flag * 2}return ans - 1 };

    由于解法三是直接拿整數(shù)本身進(jìn)行與操作計(jì)算的,所以沒有像解法二額外將整數(shù)轉(zhuǎn)換為字符串,增加了空間復(fù)雜度,所以解法三同解法一,空間復(fù)雜度為O(log n),空間復(fù)雜度為O(1)。

    總結(jié)

    于我個(gè)人而言,做這道題最大的收獲不是這道簡(jiǎn)簡(jiǎn)單單的題目本身,而是文中引用的兩句話。因?yàn)樽駠谶@樣的告示,可能會(huì)對(duì)今后做更多的題乃至工作中會(huì)有莫大的幫助,共勉。

    總結(jié)

    以上是生活随笔為你收集整理的每列大于0的个数_题目1342——把一个数字减少到0的步骤数的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

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